• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Multi-threading vs file access

 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi guys,

I got my mind in some kind of deadlock.
It concerns my Data class and multi-threading vs file access.
My Data class is a singleton and has a static raf datafile. The read method is not synchronized to allow multiple concurrent reads and the update method is synchronized on the datafile.
Now the problem is that both the read and update methods use the seek method to set the filepointer on the one and only datafile. So what if one thread is reading and set the filepointer and just after that another thread also wants to read and sets the filepointer some place else ? Can I catch this or should I make the read method also synchronized ??

Side question : Does the Data class need to be singleton when the raf data file is static ?
 
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Sven,

You are right: you have the potential to corrupt your data file with your current implementation.

It is up to you whether you synchronize the methods, or whether you synchronize just the data file access block of code. Normally the methods as a whole do a bit more work than just the physical read/write: they may have to validate data, convert between bytes and String arrays, and so on. Synchronizing the entire method means that other threads will be blocked while this additional work gets done - synchronizing just on the {seek & read/write} block means that you are reducing the time threads will be blocked / increasing concurrent access.

You are also correct in questioning whether you need any static variables inside a Singleton class: normally there is no point to this.

But which do you get rid of? The Singleton pattern or the static modifier on your variable? There are arguments for and against both choices .

Regards, Andrew
 
Ranch Hand
Posts: 210
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Besides that, I also think that synchronizing on the update is by far not enough. True: updates will go sequential. But, what about reads during updates ? Since you are not synchronizing on the read method there is no wait for threads to read (as you mentioned yourself) this means that one thread one is updating, thread two can read. And if you have bac luck thread two might start reading before thread one finished. And what do you get ? Yes, screwed up data...

And why do you want to synchronize on you update method anyway, you have locking, so multiple updates are handled on the logical locking level. You just want your physical locking level to hold the reads while doing the actual write operation.


There are only two kind of solutions for this:

a) synchronize on the RAF (not on the methods, but on the RAF itself) . It is simple and solves all your problems. You do have to implement logical locking though. First because it is obligated by the assignment, and second because if your doing update consitency checking you want to do the check read after you put a logical lock on the record.

b) create a read/write locking system based upon mutex. This is more complex and I seriously doubt that it is required. It will however create a perfect solution that you can defend against every question. You do not require physical locking anymore, multiple reads and writes are allowed, as long as they do not operate on the same record, which is handled by the logical locking.

But I think solution a) is good enough. Afterall, it does the trick according to the book. The only argument is the performance. But since there is nothing in the assigment about that, I dont think that will cost you points.
 
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Koen Serneels:
And why do you want to synchronize on you update method anyway, you have locking, so multiple updates are handled on the logical locking level. You just want your physical locking level to hold the reads while doing the actual write operation.



Logical locking won't prevent concurrent operations to different records on the same file, and since the RAF has one file pointer each {seek & read/write} block must be synchronized as Andrew noted.

If you want to be able to safely make concurrent reads you can cache the records, calling reads on the cache objects, but you will still have to synchronize the file writes.
 
Sven Mari�n
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, the concurrency problem I have is with setting the filepointer in the read method. This can corrupt the data with multiple simultaneous reads. A possible solution I see is to not use the seek method but use the read method with offset parameter which makes every read an atomic process and does not affect other reads.

As for locking, I'm implementing both physical and logical locking schemes. My physical locking is based upon the reader/writer lock pattern which allows multiple reads, uses a queueing mechanism and blocks all new reads when there is a write lock. Now the logical locking scheme emphasizes on record level access and ensures that only one thread can update a certain record, if I'm correct.
The thing that still gets me confused is where, how and on what object do I need to synchronize ?? Also, I'm thinking about losing the singleton and make the RAF static...

As we say here : 'k zie door de bomen 't bos niet meer.
 
Jim Janssens
Ranch Hand
Posts: 210
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hehe, taalgenoot

Ok, what I understand from your story is that you are using read/write locking on logical level. that gives you this:

- multiple reads, as long as no write lock is given
- when a write lock is given, all other reads must wait
- when a write lock is given, all other writes are appended to the queue

So, you do not have multiple writes, only multiple reads when there is no writing going on...

In that case you *won't* need physical locking. The only thing you have to do is make sure that no multiple reads use the same RAF, so you create a pool of RAF's . This way every read occurs at the same time on a different RAF. The fact of having x number of RAF objects is no performance issue because creating a RAF instance is a very low cost (check the code for yourself) .

Note: the RAF pool was a sugesting made by Monk House on a question of mine. He also sugested to make sure that the underlying OS supports the handling of more then one RAF on the same file handle. So you could make this check first in your code and depending on the result create a pool varying from 1 RAF to x RAF's.

Now, with this system (read/write locking) keep this deadlock scenario in mind:

- Thread A wants to update record 1. It gives his version of record 1 + the updated version of record 1 which should go in the database.

- Thread A obtains write lock for record 1

- Thread A does a read, to see if the version thread A has of record 1 is still valid (making sure that it has not been changed in the mean time)

Since record one is allready locked for writing, the read cannot occur, and you have a deadlock. You could ofcourse make some bypass code, but I don't think thats the way to go.

I would solve the locking fairly simple:

Just implement a queue based write locking on logical level, and syncrhonize on the read/write methods as physical locking level. This way you:

- do not have multiple writes because of the queue
- you have the use no cpu cycle thing from the assignment covered when using a queue
- still can do reads after you put a logical lock on the record
- no reads can occur while the actual write takes place->due to syncrhonized
- no writes can occur when reads are taking place->due to syncrhonized

I think this solves about all the possible locking problems.

There are downsides of this solution, but all of them are performance wise. For example: you cannot do multiple reads at the same time, because of syncrhonized.

So the solution using read/write locking and no physical locking will perform better. But the assignment does not talk about performance ...

Suggestions about this are more then welcome
 
Ranch Hand
Posts: 181
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I use a cache in my implementation and makes things a whole lot easier. When I do synchronized update, it will first update the database, then it will update the cache. My read method does not read from the database file but reads from the cache instead. This prevents corrupting my data. What do you think?
 
Yes, my master! Here is the tiny ad you asked for:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic