In multi-threading, in order to make thread safety, we often use synchronized and Lock for code synchronization and locking, but what is the specific difference between the two, and which scenarios are suitable for use may not be clear. The main differences are roughly as follows:
the difference
1. Synchronized is a java keyword, and Lock is an interface in java
2. Synchronized will automatically release the lock, and Lock must manually release the lock
3. Synchronized is uninterruptible, and Lock can be interrupted or uninterrupted
4. Through Lock, you can know whether the thread has got the lock, but synchronized cannot
5. Synchronized can lock methods and code blocks, while Lock can only lock code blocks
6. Lock can use the read lock to improve the efficiency of multi-threaded reading
7. Synchronized is a non-fair lock, ReentranLock can control whether it is a fair lock
From the Lock interface, we can see that there are mainly five methods. The functions of these methods can be seen from the comments:
- lock(): Acquire the lock, if the lock is temporarily used, wait forever
- unlock(): release the lock
- tryLock(): Note that the return type is boolean, if the lock is occupied when the lock is acquired, it returns false, otherwise it returns true
- tryLock(long time, TimeUnit unit): Compared with tryLock(), it gives a time limit to ensure the waiting time for the parameter
- lockInterruptibly (): a way to get the lock, if the thread is waiting to acquire the lock to enter the stage, you can interrupt this thread, to do something else
by the above explanations, can generally be explained in the previous section, "Lock Type (lockInterruptibly())", "lock state (tryLock())" and other issues, as well as the process of acquiring in the previous sub. What I wrote is "roughly you can try to acquire the lock, and the thread can not wait forever." Yes, the reason.
lock():
public class LockTest {
private Lock lock = new ReentrantLock();
private void method(Thread thread) {
lock.lock();
try {
System.out.println(thread.getName() + " has gotten the lock!");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(thread.getName() + " has unlocked the lock!");
lock.unlock();
}
}
public static void main(String[] args) {
final LockTest test = new LockTest();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
operation result:
t1 has gotten the lock!
t1 has unlocked the lock!
t2 has gotten the lock!
t2 has unlocked the lock!
tryLock():
public class LockTest {
private Lock lock = new ReentrantLock();
private void method(Thread thread) {
if (lock.tryLock()) {
lock.lock();
try {
System.out.println(thread.getName() + " has gotten the lock!");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(thread.getName() + " has unlocked the lock!");
lock.unlock();
}
} else {
System.out.println("I'm "+thread.getName()+". Someone has gotten the lock!");
}
}
public static void main(String[] args) {
LockTest test = new LockTest();
Thread t1 = new Thread(() -> test.method(Thread.currentThread()), "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
test.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
operation result:
t1 has gotten the lock!
t1 has unlocked the lock!
I'm t2. Someone has gotten the lock!
Seeing this, I believe everyone will also use how to use Lock. I won’t go into details about tryLock(long time, TimeUnit unit) and lockInterruptibly(). The former mainly has a waiting time, and a waiting time is written in the test code. The latter mainly waits for an interrupt and throws an interrupt exception, which is not frequently used. If you like to explore, you can study it yourself.