aspose file tools*
The moose likes Threads and Synchronization and the fly likes How exactly locks work in this code? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "How exactly locks work in this code?" Watch "How exactly locks work in this code?" New topic
Author

How exactly locks work in this code?

Saleh Feek
Greenhorn

Joined: Sep 19, 2012
Posts: 14
This code is based on oracle code: http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html

I modified it, just to be more traceable.

I want to understand something about acquiring locks by threads, it is clear in the output under the code below.


The output of this code is usually: (I add the numbers to the output)
................................
1- Thread that uses Alphonse is checking free lock for Gaston
2- Thread that uses Alphonse found out that Alphonse lock is true and Gaston lock is true
3- Both locks are free so Alphonse started executing bow() normally But not finished yet
4- Thread that uses Gaston is checking free lock for Alphonse
5- Thread that uses Gaston found out that Gaston lock is false and Alphonse lock is false
6- The Thread that uses Gaston found that the object Alphonse lock is not free so Gaston exits bow() normally
7- Alphonse has finished processing bow() and releases locks
................................


This seems a contradiction

At (output) line 2: the thread that uses Alphonse got the locks of both Alphonse and Gaston by using
myLock = this.lock.tryLock();
yourLock = bower.lock.tryLock();


At line 4: How can another thread use Gaston object, whereas its lock is already held by another thread? (see line 2 above)

At line 5: (Gaston lock is false); so how can it be used by another thread?
...

I hope I was clear.

Thank you
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

When another thread holds a lock, it doesn't mean you "can't 'use' that object". It just means you can't acquire that lock.
Saleh Feek
Greenhorn

Joined: Sep 19, 2012
Posts: 14
Thank you Jeff Verdegan
Jeff Verdegan wrote:When another thread holds a lock, it doesn't mean you "can't 'use' that object". It just means you can't acquire that lock.


But from Oracle:
A lock is a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: only one thread at a time can acquire the lock and all access to the shared resource requires that the lock be acquired first.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Saleh Feek wrote:Thank you Jeff Verdegan
Jeff Verdegan wrote:When another thread holds a lock, it doesn't mean you "can't 'use' that object". It just means you can't acquire that lock.


But from Oracle:
A lock is a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: only one thread at a time can acquire the lock and all access to the shared resource requires that the lock be acquired first.


The "shared resource" is not the Lock object, nor is it the Friend object that's using that lock. It's the Lock object's conceptual lock that you obtain by calling lock(), or you can view it as the code that's protected by being between lock() and unlock().


The "Commonly" at the beginning of that sentence means "This is how one usually uses it." So it's up to you to define what resource you're protecting with the locks, and to make sure that all access to that resource is protected.

Acquiring a Lock's lock using Lock.lock() is just like acquiring any object's lock using the synchronized keyword. All it means is that no other thread can acquire that lock until you release it.

(And a Lock object has two distinct, independent conceptual locks. One you get by calling lock(), and one you get by synchronizing on that Lock object.)

Saleh Feek
Greenhorn

Joined: Sep 19, 2012
Posts: 14
Thank you for help Jeff Verdegan.

According to what I understand now (am I right?)

When, say thread1 acquires the locks of both Alphonse and Gaston objects.

Another thread say thread2 can't acquire the lock of Gaston (until released by thread1), but can use Gaston.

...........
When using synchronized keyword with methods. If thread1 uses a synchronized method of object objA, then no other thread can use any synchronized method of objA. This is useful because it ensures that no other thread can invoke any method labelled with synchronized of objA until its lock is released by thread1 by finishing objA method processing.
...........

According to what I understand now (am I right?):

Using lock.trylock()..lock.unlock is different from using synchronized in that if thread1 uses objA, then another thread can use all of objA methods even if it can't aquire its lock.

The point of usefulness of using trylock() is just in a condition statements to check whether lock is acquired or not, and depending on the returned boolean value, programmer decide to process things or to exit of objA method.

In synchronized mechanism, different threads are forced to not use the synchronized methods of the same object until it is lock is released. In other words one thread at a time can use the synchronized methods of the same object.

In lock.trylock()..lock.unlock mechanism, different threads are not blocked from using the same object even if its lock is not acquired yet, but they can't acquire its lock at the same time. Then it is the responsibility of the programmer to check acquiring the locks, and decide to process things of the same object when true is returned. (programmer also can decide to process things when false is returned).


Am I right?
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40


BTW, this is also how Solaris threads, Windows threads, Posix threads, and likely most threading environments work. Owning a lock only prevents other threads from owning the lock. It is cooperative. To protect anything, whether it is data, code, or any object, the threading system assumes that the threads will make sure it owns the correct lock before accessing the resource. It doesn't actually "lock" anything, well, besides the lock itself.

Henry

Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18896
    
  40

Saleh Feek wrote:Thank you for help Jeff Verdegan.

According to what I understand now (am I right?)

When, say thread1 acquires the locks of both Alphonse and Gaston objects.

Another thread say thread2 can't acquire the lock of Gaston (until released by thread1), but can use Gaston.

...........
When using synchronized keyword with methods. If thread1 uses a synchronized method of object objA, then no other thread can use any synchronized method of objA. This is useful because it ensures that no other thread can invoke any method labelled with synchronized of objA until its lock is released by thread1 by finishing objA method processing.
...........

According to what I understand now (am I right?):

Using lock.trylock()..lock.unlock is different from using synchronized in that if thread1 uses objA, then another thread can use all of objA methods even if it can't aquire its lock.

The point of usefulness of using trylock() is just in a condition statements to check whether lock is acquired or not, and depending on the returned boolean value, programmer decide to process things or to exit of objA method.

In synchronized mechanism, different threads are forced to not use the synchronized methods of the same object until it is lock is released. In other words one thread at a time can use the synchronized methods of the same object.

In lock.trylock()..lock.unlock mechanism, different threads are not blocked from using the same object even if its lock is not acquired yet, but they can't acquire its lock at the same time. Then it is the responsibility of the programmer to check acquiring the locks, and decide to process things of the same object when true is returned. (programmer also can decide to process things when false is returned).


Am I right?


You are overthinking this... if you need something protected, have all you threads own the correct lock before accessing that something that needs access to be exclusive. Period. What the lock is, and how you grab it is up to you -- you can simply call the lock() method, or you can have some sort of complex mechanism around tryLock(), doesn't matter. If the thread owns the lock, it should have access. If you access the resource without the lock, then you messed up.

Henry
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Saleh Feek wrote:Thank you for help Jeff Verdegan.

According to what I understand now (am I right?)

When, say thread1 acquires the locks of both Alphonse and Gaston objects.

Another thread say thread2 can't acquire the lock of Gaston (until released by thread1), but can use Gaston.

...........
When using synchronized keyword with methods. If thread1 uses a synchronized method of object objA, then no other thread can use any synchronized method of objA. This is useful because it ensures that no other thread can invoke any method labelled with synchronized of objA until its lock is released by thread1 by finishing objA method processing.
...........


Correct.

According to what I understand now (am I right?):

Using lock.trylock()..lock.unlock is different from using synchronized in that if thread1 uses objA, then another thread can use all of objA methods even if it can't aquire its lock.


There's no difference there. Whether it's Lock.tryLock()/unlock() or synchronized, either way, all you're doing is acquiring a lock and preventing any other thread from acquiring that lock. The difference between the two approaches is that using Lock's methods you get more control (you can check first to see if the lock is available with tryLock() rather than just being stuck waiting, you can unlock in a different order than you lock, etc.), but on the other hand, Lock's methods also require you to explicitly release the lock, whereas with synchronized it's done automatically for you.

The effect is the same though: You have acquired a lock, and no other thread can acquire it until you release it, and the only code that is affected by that is code that also explicitly tries to acquire that lock. As Henry said, it's cooperative. The only code affected is code that has been explicitly written to use the same lock.

The point of usefulness of using trylock() is just in a condition statements to check whether lock is acquired or not, and depending on the returned boolean value, programmer decide to process things or to exit of objA method.


Yes. If you have a situation that's "execute this code now if possible, otherwise don't bother," then tryLock() is appropriate. (Although that doesn't necessarily mean you have to exit the method. There can be additional processing in the same method that doesn't require the lock.)

In synchronized mechanism, different threads are forced to not use the synchronized methods of the same object until it is lock is released. In other words one thread at a time can use the synchronized methods of the same object.


In more precise other words, only one thread at a time can own that object's lock (or "monitor" as it's sometimes called). Not being able to execute a synchronized method is simply a consequence of the fact that the method can't be executed until we obtain the lock.

In lock.trylock()..lock.unlock mechanism, different threads are not blocked from using the same object even if its lock is not acquired yet,


Exactly the same as with synchronization. We're not blocked from executed code that's not protected by the lock, but we are blocked from executing code that is protected by the same lock.


Saleh Feek
Greenhorn

Joined: Sep 19, 2012
Posts: 14
It is clear now.

Thank you very much Jeff Verdegan, Henry Wong
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: How exactly locks work in this code?