In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article is to share with you about what the mechanism of various locks in java is. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Preface
Summarize the common locks in java
Distinguish between individual locking mechanisms and how to use them
Use the method lock name to examine whether threads want to lock synchronous resources optimistic lock and pessimistic lock synchronous resources, whether to block or not can use spin lock one thread multiple processes to acquire the same lock can be reentered multiple threads share a lock read-write lock (write shared lock) whether multiple threads compete to queue fair lock and unfair lock 1. Optimistic lock and pessimistic lock
Pessimistic lock: you can't have multiple people at the same time, lock it first when you execute it. Many of these locking mechanisms are used in traditional relational databases, such as row locks, table locks, read locks, write locks and so on.
Optimistic lock: through whether the version number is consistent or not, that is, adding a version to the data, synchronously updating the data, and adding the version number. Will not lock, judge the version number, can be operated by multiple people, similar to grabbing tickets in life. Every time I go to get the data, I think that others will not change it, so it will not be locked, but when I update it, I will judge whether others have updated the data during this period. We can use mechanisms such as version number. Optimistic locks are suitable for multi-read applications, which can improve throughput. Redis uses this check-and-set mechanism to implement transactions.
(optimistic locks can be implemented using version number mechanism and CAS algorithm.)
Demonstrate pessimistic lock and optimistic lock through specific cases
In the redis framework
Before executing multi, execute the command watch
The specific format is as follows
Watch key1 [key2]
The specific code format is as follows
127.0.0.1 flushdbOK127.0.0.1:6379 > set add 100OK127.0.0.1:6379 > watch addOK127.0.0.1:6379 > multiOK127.0.0.1:6379 (TX) > incrby add 20QUEUED127.0.0.1:6379 (TX) > exec1) (integer) 120127.0.0.1
Flushdb is emptying the database
But if you type exec on another server, an error will be displayed
Because the optimistic lock is used, the version will change after it is modified.
In general:
Pessimistic lock: when everyone gets something done alone, execute the lock and unlock. Solve problems in concurrency, do not support concurrent operations, can only operate one by one, low efficiency
Optimistic lock: every time you perform something, you compare the data version number, who submits first and who submits the version number first.
two。 Fair lock and unfair lock
Fair lock: first come, first served
Unfair lock: not in order, can jump the queue
Fair lock: relatively low efficiency
Unfair locks: efficient, but threads tend to starve to death
Through this function Lock lock = new ReentrantLock (true);. Create a reentrant lock, with true for fair lock and false for unfair lock. Default unfair lock
By viewing the source code
ReentrantLock (true) with parameters is a fair lock
ReentrantLock (false) is an unfair lock
Mainly call NonfairSync () and FairSync ()
Public ReentrantLock () {sync = new NonfairSync ();} / * * Creates an instance of {@ code ReentrantLock} with the * given fairness policy. * * @ param fair {@ code true} if this lock should use a fair ordering policy * / public ReentrantLock (boolean fair) {sync = fair? New FairSync (): new NonfairSync ();}
The specific source code of unfair lock and fair lock
View the source code of the fair lock
Static final class FairSync extends Sync {private static final long serialVersionUID =-3000897897090466540L; / * Acquires only if reentrant or queue is empty. * / final boolean initialTryLock () {Thread current = Thread.currentThread (); int c = getState (); if (c = = 0) {if (! hasQueuedThreads () & & compareAndSetState (0,1)) {setExclusiveOwnerThread (current); return true;}} else if (getExclusiveOwnerThread () = = current) {if (+ + c)
< 0) // overflow throw new Error("Maximum lock count exceeded"); setState(c); return true; } return false;} 通过代码实例具体操作 //第一步 创建资源类,定义属性和和操作方法class LTicket { //票数量 private int number = 30; //创建可重入锁 private final ReentrantLock lock = new ReentrantLock(true); //卖票方法 public void sale() { //上锁 lock.lock(); try { //判断是否有票 if(number >0) {System.out.println (Thread.currentThread (). GetName () + ": sell" + (number--) + "remaining:" + number);} finally {/ / unlock lock.unlock () } public class LSaleTicket {/ / the second step is to create multiple threads and call the operation method of the resource class / / create three threads public static void main (String [] args) {LTicket ticket = new LTicket (); new Thread (()-> {for (int I = 0; I)
< 40; i++) { ticket.sale(); }},"AA").start(); new Thread(()->{for (int I = 0; I)
< 40; i++) { ticket.sale(); } },"BB").start(); new Thread(()->{for (int I = 0; I)
< 40; i++) { ticket.sale(); } },"CC").start(); }} 结果截图如下 都是A线程执行,而BC线程都没执行到,出现了非公平锁 具体改变其设置可以通过可重入锁中的一个有参构造方法 修改代码为private final ReentrantLock lock = new ReentrantLock(true); 代码截图为 3. 可重入锁 可重入锁也叫递归锁 而且有了可重入锁之后,破解第一把之后就可以一直进入到内层结构 Object o = new Object();new Thread(()->{synchronized (o) {System.out.println (Thread.currentThread (). GetName () + "outer layer"); synchronized (o) {System.out.println (Thread.currentThread (). GetName () + "middle layer"); synchronized (o) {System.out.println (Thread.currentThread (). GetName () + "inner layer") }, "T1") .start ()
Synchronized (o) stands for locking the block of code in the current {}
The above are all synchronized locking mechanisms.
The lock locking mechanism is explained below.
Public class SyncLockDemo {public synchronized void add () {add ();} public static void main (String [] args) {/ / Lock demo reentrant lock Lock lock = new ReentrantLock (); / / create thread new Thread (()-> {try {/ / lock lock.lock ()) System.out.println (Thread.currentThread (). GetName () + "outer layer"); try {/ / lock lock.lock (); System.out.println (Thread.currentThread (). GetName () + "inner layer") } finally {/ / release lock lock.unlock ();}} finally {/ / release as lock.unlock ();}}, "T1") .start () / / create a new thread new Thread (()-> {lock.lock (); System.out.println ("aaaa"); lock.unlock ();}, "aa") .start ();}}
For a nested lock in the same lock, the inner nested lock can still be output without being unlocked, but if you jump out of that thread, executing another thread will cause a deadlock
To grasp the concept of locking and unlocking, write down
4. Read-write lock (shared lock and exclusive lock)
A read lock is a shared lock and a write lock is an exclusive lock
A concrete implementation of shared Lock
Read-write locks manage a set of locks, one read-only lock and one write lock.
Read-write lock: a resource can be accessed by multiple read threads or by one write thread, but there can be no read-write thread, read-write mutual exclusion, read-write sharing (exclusive write lock, read lock sharing, write lock priority is higher than read lock)
Read-write lock ReentrantReadWriteLock
The read lock is the ReentrantReadWriteLock.ReadLock,readLock () method
Write the lock as the ReentrantReadWriteLock.WriteLock,writeLock () method
Create a read-write lock object private ReadWriteLock rwLock = new ReentrantReadWriteLock ()
Write lock rwLock.writeLock (). Lock ();, unlock to rwLock.writeLock (). Unlock ()
Read lock plus lock rwLock.readLock (). Lock ();, unlock to rwLock.readLock (). Unlock ()
Case study:
Simulate multithreading to fetch and read data in map
The complete code is as follows
/ / Resource class class MyCache {/ / create map collection private volatile Map map = new HashMap (); / / create read-write lock object private ReadWriteLock rwLock = new ReentrantReadWriteLock (); / / put data public void put (String key,Object value) {/ / add write lock rwLock.writeLock () .lock () Try {System.out.println (Thread.currentThread (). GetName () + "write operation" + key); / pause for a while TimeUnit.MICROSECONDS.sleep (300); / / play data map.put (key,value); System.out.println (Thread.currentThread (). GetName () + "finished" + key) } catch (InterruptedException e) {e.printStackTrace ();} finally {/ / release write lock rwLock.writeLock () .unlock ();}} / / fetch data public Object get (String key) {/ / add read lock rwLock.readLock () .lock (); Object result = null Try {System.out.println (Thread.currentThread (). GetName () + "reading operation" + key); / / pause for a while TimeUnit.MICROSECONDS.sleep (300); result = map.get (key); System.out.println (Thread.currentThread (). GetName () + "finished" + key) } catch (InterruptedException e) {e.printStackTrace ();} finally {/ / release read lock rwLock.readLock (). Unlock ();} return result;}} public class ReadWriteLockDemo {public static void main (String [] args) throws InterruptedException {MyCache myCache = new MyCache (); / / create a thread to put data for (int I = 1) I {myCache.put (num+ "", num+ ");}, String.valueOf (I)) .start ();} TimeUnit.MICROSECONDS.sleep (300); / / create a thread to fetch data for (int I = 1; I {myCache.get (num+");}, String.valueOf (I)) .start () }}}
5. Mutex lock
Mutex is a conventional implementation of exclusive lock, which means that only one visitor is allowed to access a resource at the same time, which is unique and exclusive.
Pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;// creates a mutex and initializes pthread_mutex_lock (& mutex); / / A pair of threads are locked while other threads block waiting for the thread to release the lock / / the code segment to be executed pthread_mutex_unlock (& mutex); / / release lock 6 after execution. Spin lock
Check out the explanation of Baidu Encyclopedia, as follows:
It proposes a locking mechanism to protect shared resources. In fact, spin locks are similar to mutexes in that they are designed to solve the mutually exclusive use of a resource. Whether it is a mutex or a spin lock, there can be at most one holder at any time, that is, at most one execution unit can acquire the lock at any one time. But the two are slightly different in scheduling mechanism. For mutexes, resource applicants can only go to sleep if the resource is already occupied. But the spin lock does not cause the caller to sleep, and if the spin lock is already held by another execution unit, the caller loops there to see if the holder of the spin lock has released the lock, hence the name "spin".
Generally speaking, when a thread acquires a lock, if the lock has been acquired by another thread, then the thread will cycle and wait, and then continue to determine whether the lock can be successfully acquired, and will not exit the loop until the lock is acquired. The thread that acquired the lock is always active, but does not perform any valid tasks.
Its characteristics are:
Hold the lock for too long, consuming CPU
Unable to satisfy the thread with the longest waiting time to acquire the lock first. Unfair locks will have the problem of "thread hunger"
The spin lock does not switch the thread state, is in the user mode (does not transition to the kernel state), is always active, does not make the thread enter the blocking state, reduces unnecessary context switching, and executes quickly.
The simulation algorithm is as follows
Do {bread1; while (b) {lock (bus); b = test_and_set (& lock); unlock (bus);} / / critical region / / lock = 0; / / the rest} while (1) 7. No lock / bias lock / lightweight lock / heavyweight lock
No lock: no resource is locked. All threads can access and modify the same resource, but only one thread can modify it successfully.
Biased lock: means that a piece of synchronization code is accessed by a thread all the time, then the thread automatically acquires the lock, reducing the cost of acquiring the lock
Lightweight lock: when a lock is biased towards a lock and is accessed by another thread, the bias lock will be upgraded to a lightweight lock, and other threads will try to acquire the lock in the form of spin without blocking, thus improving performance
Heavy lock: thread concurrency increases, thread spins more than a certain number of times, or a thread holds a lock, a thread is spinning, and a thread needs to access
Thank you for reading! This is the end of this article on "what is the mechanism of all kinds of locks in java". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.