Why not use a lock attempt in java?

I read this section and this blog article about trying with resource locks as a question popped up in my head. But actually, I would rather try with a lock, I mean without creating an instance. It will free us from detailed

lock.lock(); try { //Do some synchronized actions throwing Exception } finally { //unlock even if Exception is thrown lock.unlock(); } 

More likely it will look:

 ? implements Unlockable lock ; ... try(lock) //implicitly calls lock.lock() { //Do some synchronized actions throwing Exception } //implicitly calls finally{lock.unlock();} 

Thus, it will not be TWR, but just some kind of cleanup.

Do you have any technical reasons to suggest describing why this would not be a reasonable idea?

EDIT: to clarify the difference between what I suggest and the simple synchronized(lock){} block, check this snippet:

 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Test { public static void main(String[] args) { ReentrantLock locker =new ReentrantLock(); Condition condition = locker.newCondition(); Thread t1 = new Thread("Thread1") { @Override public void run(){ synchronized(locker){ try { condition.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("Thread1 finished"); } } } ; Thread t2 = new Thread("Thread2") { @Override public void run(){ synchronized(locker){ Thread.yield(); condition.signal(); System.out.println("blabla2"); } } } ; t1.start(); t2.start(); } } 

Execution will result in an IllegalMonitorStateException , so the lock () and unlock () methods are implicitly called in the synchronized block.

+5
source share
2 answers

If you had to deal with such a simple case when the lock / unlock pattern was limited to a narrow area like this, you probably would not want to use a more complex Lock , and you should probably use only the synchronized . However, if for some reason you need this with a more complex Lock object, it should be relatively easy to create a wrapper around Lock that implements AutoCloseable in order to be able to do just that. Example:

 class AutoUnlock implements AutoCloseable { private final Lock lock; public static AutoUnlock lock(Lock lock) { lock.lock(); return new AutoUnlock(lock); } public static AutoUnlock tryLock(Lock lock) { if (!lock.tryLock()) { throw new LockNotAcquiredException(); } return new AutoUnlock(lock); } @Override public void close() { lock.unlock(); } private AutoUnlock(Lock lock) { this.lock = lock; } } 

Using the wrapper as shown above, you can:

 try (AutoUnlock autoUnlock = AutoUnlock.lock(lock)) { // ... do whatever that requires the lock ... } 

In this case, the Lock class is usually used for very complex locking scenarios, where this will not be particularly useful. For example, Lock objects can be locked in one function of the class and then unlocked in another function (for example, locking a row in the database in response to an incoming call to a remote procedure, and then unlocking this row in response to a later RPC) and thus To have such a wrapper or to make Lock AutoCloseable, in itself, will be limited use for how it is actually used. For simpler scenarios, the existing parallel data structure is most often used or used synchronously.

+4
source

This answer serves to explain the behavior of your editing. The purpose of synchronized is to lock the monitor of this object when the thread enters the block (waiting if it is unavailable) and freeing it when the thread exits the block.

Lock is a higher level abstraction.

Lock implementation provides wider lock operations than can be obtained using synchronized methods and operators.

You can use it to block the boundaries of a method. synchronized cannot do this, so Lock cannot be implemented exclusively with synchronized , and no implementation I have ever seen uses it. Instead, they use other templates, such as compare and share . They use this for an atom of an atom in a Lock object that marks a specific thread as the owner of the lock.

In the code snippet you are trying to call

 condition.signal(); 

in a thread that does not have Lock from which the condition was created. javadoc claims

An implementation may (and usually) require the current thread to hold the lock associated with this condition when this method is called . Implementations should document this prerequisite and any action taken if the lock is not held. Typically, an exception such as IllegalMonitorStateException will be thrown.

What happened here.

Performance

 synchronized (lock) {} 

makes the current thread lock (and then releases) the monitor on the object referenced by Lock . Performance

 lock.lock(); 

forces the current thread to set some state in the object referenced by Lock , which identifies it as the owner.

0
source

Source: https://habr.com/ru/post/1204960/


All Articles