In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
How to achieve a spin distributed lock, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.
The full name of AQS is AbstractQueuedSynchronizer, abstract queue synchronizer
In the ReentrantLock class, let's take a look at how locking is implemented.
Private final Sync sync;public void lock () {sync.lock ();}
This sync is a subclass of AQS and is an abstract class
Abstract static class Sync extends AbstractQueuedSynchronizer
Its lock () method is an abstract method
Abstract void lock ()
The concrete implementation of sync is two subclasses, the fair lock class
Static final class FairSync extends Sync
And unfair locks.
Static final class NonfairSync extends Sync
Here we mainly use unfair locks, because most of the locks we usually use are unfair locks. In unfair locks, the implementation of the lock () method is as follows
The internal method of final void lock () {/ / AQS, unlocked contention for the state of state in AQS, the initial value of state is 0, and the one that acquires the lock changes 0 to 1if (compareAndSetState (0,1)) / / the exclusive main thread setExclusiveOwnerThread (Thread.currentThread ()) that sets the current thread to AQS with state = 1; else acquire (1);}
In the AbstractQueuedSynchronizer class
Private static final long stateOffset
In the static code block, we can see that the stateOffset takes state, and the state is a multithreaded visible volatile.
StateOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField ("state")); private volatile int state;protected final boolean compareAndSetState (int expect, int update) {/ / See below for intrinsics setup to support this return unsafe.compareAndSwapInt (this, stateOffset, expect, update);} private transient Thread exclusiveOwnerThread;protected final void setExclusiveOwnerThread (Thread thread) {exclusiveOwnerThread = thread;}
Here unsafe.compareAndSwapInt () is implemented in C, and we can use java to simulate this method.
@ Slf4j@Getterpublic class GetState {private AtomicReference state = new AtomicReference (0); private boolean lockState () {while (true) {if (state.compareAndSet (0Magne1)) {return true;}} private void unlockState () {state.set (0);} @ AllArgsConstructor private static class Task implements Runnable {private GetState getState @ Override public void run () {if (getState.lockState ()) {log.info (Thread.currentThread (). GetName () + "acquire Lock");}} public static void main (String [] args) throws InterruptedException {ExecutorService service = Executors.newFixedThreadPool (16); GetState state = new GetState (); for (int I = 0bot I)
< 10;i++) { service.execute(new Task(state)); }while (state.getState().get() == 1) { Thread.sleep(1000); state.unlockState(); } service.shutdown(); }} 打印日志(每秒打印一条) 15:35:42.953 [pool-1-thread-1] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-1获取锁 15:35:43.953 [pool-1-thread-9] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-9获取锁 15:35:44.957 [pool-1-thread-5] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-5获取锁 15:35:45.962 [pool-1-thread-2] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-2获取锁 15:35:46.962 [pool-1-thread-7] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-7获取锁 15:35:47.962 [pool-1-thread-3] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-3获取锁 15:35:48.967 [pool-1-thread-8] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-8获取锁 15:35:49.969 [pool-1-thread-6] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-6获取锁 15:35:50.970 [pool-1-thread-4] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-4获取锁 15:35:51.971 [pool-1-thread-10] INFO com.guanjian.websocket.tomic.GetState - pool-1-thread-10获取锁 Process finished with exit code 0 现在我们可以来写一个支持自旋的分布式锁了。 public class SpinDistributedLock {private volatile AtomicReference state = new AtomicReference(false); public boolean lock(RedisService redisService,String key,String value,int expire) {while (true) {if (state.compareAndSet(false, RedisTool.tryGetDistributedLock(redisService,key,value,expire))) {if (state.get()) {return true; } } } }public void unlock(RedisService redisService,String key,String value) {state.set(!RedisTool.releaseDistributedLock(redisService,key,value)); }} 常规分布式锁可以参考采用redis token,分布式锁的接口幂等性实现 现在我们来进行一个简单的测试,先不使用分布式锁 我们在redis中手动设置一个键count,0 127.0.0.1:6379>Set count 0
OK
Our aim is to accumulate this count, but we can't let it exceed 10.
Servicepublic class NoDistributedTest {@ Autowired private RedisService redisService; private class Task implements Runnable {@ Override public void run () {if (Integer.valueOf (redisService.get ("count"))
< 10) {redisService.incr("count"); } } }@PostConstruct public void test() { ExecutorService service = Executors.newFixedThreadPool(16); for (int i = 0;i < 100000;i++) { service.execute(new Task()); } service.shutdown(); }} 我们启动两个进程,两个进程启动完成后,我们再来看一下该键的值。 127.0.0.1:6379>Get count
"15"
At this time, we can see that the number is more than 10. 5% without locks.
Now test with distributed locks.
Reset the count key to 0
127.0.0.1 set count 6379 > 0
OK
@ Slf4j@Servicepublic class DistributedTest {private SpinDistributedLock lock = new SpinDistributedLock (); @ Autowired private RedisService redisService; private class Task implements Runnable {@ Override public void run () {try {lock.lock (redisService, "countlock", "countlock", 3); log.info (Thread.currentThread (). GetName () + "enter the lock"); if (Integer.valueOf (redisService.get ("count"))
< 10) {redisService.incr("count"); } } finally {lock.unlock(redisService,"countlock","countlock"); log.info(Thread.currentThread().getName() + "释放锁"); } } }@PostConstruct public void test() { ExecutorService service = Executors.newFixedThreadPool(16); for (int i = 0;i < 100000;i++) { service.execute(new Task()); } service.shutdown(); }} 同样启动两个进程或者更多进程,启动完成后,我们来看一下count键的值 127.0.0.1:6379>Get count
"10"
Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.
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.