Home  >  Article  >  Java  >  A brief introduction to the Java multi-threading keywords volatile, lock and synchronized

A brief introduction to the Java multi-threading keywords volatile, lock and synchronized

不言
不言Original
2018-09-25 15:36:101928browse

This article brings you a brief introduction to the Java multi-threading keywords volatile, lock and synchronized. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. help.

1. Volatile

The memory semantics of volatile writing and volatile reading:

Thread A writes a volatile variable, which is essentially thread A writing to the memory that will be read next. A thread of this volatile variable issued a message (which modified the shared variable). When thread B reads a volatile variable, in essence, thread B receives the message sent by a previous thread (the modification of the shared variable before writing the volatile variable). Thread A writes a volatile variable, and then thread B reads the volatile variable. This process is essentially thread A sending a message to thread B through main memory.

Memory semantics of lock release and lock acquisition:

Thread A releases a lock. In essence, thread A sends a message to a thread that will next acquire the lock (thread A shares a Variable modification) message. Thread B acquires a lock. In essence, thread B receives a message sent by a previous thread (which modified the shared variable before releasing the lock). Thread A releases the lock, and then thread B acquires the lock. This process is essentially thread A sending a message to thread B through main memory.

Summary: The role of the volatile keyword is to make variables visible (visible) across multiple threads, but volatile alone cannot guarantee thread safety. The volatile keyword does not have the synchronized keyword. Atomic.

2. lock

Lock is an interface:

public interface Lock {  
   void lock();     
   void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

lock(), tryLock(), tryLock(long time, TimeUnit unit) and lockInterruptibly() are used to Get the lock.

The unLock() method is used to release the lock. The tryLock() method has a return value, which means it is used to try to acquire the lock. If the acquisition is successful, it returns true. If the acquisition fails (that is, the lock has been acquired by another thread), it returns false, which means that this method is no matter what. will return immediately. You won't be waiting there when you can't get the lock. The tryLock(long time, TimeUnit unit) method is similar to the tryLock() method, but the difference is that this method will wait for a certain period of time when it cannot get the lock. If it cannot get the lock within the time limit, it will return false. Returns true if the lock was obtained initially or during the waiting period. The lockInterruptibly() method is special. When acquiring a lock through this method, if the thread is waiting to acquire the lock, the thread can respond to the interrupt, that is, interrupt the waiting state of the thread. That is to say, when two threads want to acquire a lock through lock.lockInterruptibly() at the same time, if thread A acquires the lock at this time, and thread B is only waiting, then the threadB.interrupt() method is called on thread B. Can interrupt the waiting process of thread B.

lock can be interrupted during the process of acquiring the lock. lock can try to acquire the lock. If the lock is held by another thread, it will return false and will not cause the current thread to sleep. When lock tries to acquire the lock, it passes in a time parameter. If the lock is not acquired within this time range, the request is terminated. synchronized will automatically release the lock, but lock will not automatically release the lock. Note: lock() can be used to lock a piece of code, so that other code needs to wait before the lock is released. It should be noted that lock will not automatically release the lock like synchronized, so it must be placed in a try-finally block. , ensuring the lock is released.

Lock and synchronized have the following differences:

1) Lock is an interface, while synchronized is a keyword in Java, and synchronized is a built-in language implementation;

2) When an exception occurs, synchronized will automatically release the lock occupied by the thread, so it will not cause a deadlock; while when an exception occurs, if Lock does not actively release the lock through unLock(), it is likely to cause a deadlock. , so when using Lock, you need to release the lock in the finally block;

3) Lock can allow the thread waiting for the lock to respond to the interrupt, but synchronized cannot. When using synchronized, the waiting thread will wait forever and cannot Respond to interruption;

 4) Through Lock, you can know whether the lock has been successfully acquired, but synchronized cannot do this.

 5) Lock can improve the efficiency of multiple threads reading operations. In terms of performance, if the competition for resources is not fierce, the performance of the two is almost the same. When the competition for resources is very fierce (that is, there are a large number of threads competing at the same time), the performance of Lock is far better than that of synchronized. Therefore, it should be selected according to the appropriate situation when using it. ReentrantLock means "reentrant lock". The concept of reentrant lock is described in the next section. ReentrantLock is the only class that implements the Lock interface, and ReentrantLock provides more methods.

3. synchronized

1. When two concurrent threads access the synchronized (this) synchronization code block in the same object object, only one thread can be executed at a time. Another thread must wait for the current thread to finish executing this code block before it can execute this code block.

2. However, when a thread accesses a synchronized (this) synchronized code block of object, another thread can still access the non-synchronized (this) synchronized code block in the object.

3. What is particularly critical is that when a thread accesses a synchronized (this) synchronized code block of object, other threads' access to all other synchronized (this) synchronized code blocks in object will be blocked.

4. The third example is also applicable to other synchronization code blocks. That is to say, when a thread accesses a synchronized(this) synchronized code block of object, it obtains the object lock of this object. As a result, other threads' access to all synchronized code parts of the object object is temporarily blocked. Scope of the synchronized keyword: Within an object instance, synchronized aMethod(){} can prevent multiple threads from accessing the synchronized method of this object at the same time (if an object has multiple synchronized methods, as long as one thread accesses one of the synchronized methods method, other threads cannot access any synchronized method in this object at the same time). At this time, the synchronized methods of different object instances do not interfere with each other. In other words, other threads can still access the synchronized method in another object instance of the same class at the same time; in the scope of a certain class, synchronized static aStaticMethod{} prevents multiple threads from accessing the synchronized static method in this class at the same time. It works on all object instances of the class.

The above is the detailed content of A brief introduction to the Java multi-threading keywords volatile, lock and synchronized. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn