通过一些demo ,尝试理解juc包下的一些类的用法;

1. 使用ReentrantLock进行同步

说明:开启四个线程,每个线程首先去执行lock方法后,睡眠不同的时间后,最后执行unlock方法。

image-20250127155327638

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@Test
public void Test() {
ReentrantLock reentrantLock = new ReentrantLock();//非公平锁

// A B C三个顾客,去银行办理业务,A先到,此时窗口空无一人,他优先获得办理窗口的机会,办理业务。
// A 耗时严重,估计长期占有窗口
new Thread(() -> {
reentrantLock.lock();
try
{
System.out.println("----come in A");
//暂停20s线程
try { TimeUnit.SECONDS.sleep(32); } catch (InterruptedException e) { e.printStackTrace(); }
}finally {
reentrantLock.unlock();
}
},"A").start();

//B是第2个顾客,B一看到受理窗口被A占用,只能去候客区等待,进入AQS队列,等待着A办理完成,尝试去抢占受理窗口。
new Thread(() -> {
reentrantLock.lock();
try
{
System.out.println("----come in B");
try { TimeUnit.SECONDS.sleep(16); } catch (InterruptedException e) { e.printStackTrace(); }
}finally {
reentrantLock.unlock();
}
},"B").start();


//C是第3个顾客,C一看到受理窗口被A占用,只能去候客区等待,进入AQS队列,等待着A办理完成,尝试去抢占受理窗口,前面是B顾客,FIFO
new Thread(() -> {
reentrantLock.lock();
try
{
System.out.println("----come in C");
try { TimeUnit.SECONDS.sleep(8); } catch (InterruptedException e) { e.printStackTrace(); }
}finally {
reentrantLock.unlock();
}
},"C").start();

new Thread(() -> {
reentrantLock.lock();
try
{
//。。。。。。
System.out.println("----come in D");
try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); }
}finally {
reentrantLock.unlock();
}
},"D").start();


while (reentrantLock.isLocked()) {
try { TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
int queueLength = reentrantLock.getQueueLength();

System.out.println("当前正在排队的人数queueLength:"+queueLength+" "+"当前持有锁的线程是:"+reentrantLock.toString());
}
}
运行结果

—-come in A
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
当前正在排队的人数queueLength:3 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread A]
—-come in B
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
当前正在排队的人数queueLength:2 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread B]
—-come in C
当前正在排队的人数queueLength:1 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread C]
当前正在排队的人数queueLength:1 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread C]
当前正在排队的人数queueLength:1 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread C]
当前正在排队的人数queueLength:1 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread C]
—-come in D
当前正在排队的人数queueLength:0 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread D]
当前正在排队的人数queueLength:0 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Locked by thread D]
当前正在排队的人数queueLength:0 当前持有锁的线程是:java.util.concurrent.locks.ReentrantLock@20ad9418[Unlocked]

2. 继承AQS实现自定义同步类之一

  1. 使用一个内部类继承抽象类AbstractQueuedSynchronizer,并实现AQS的三个protected方法;
  2. 引用上边定义的内部类,并使用内部类实现lock相关方法;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 演示锁的实现
class Mutex implements java.io.Serializable {
//静态内部类,继承AQS
private class Sync extends AbstractQueuedSynchronizer {
//是否处于占用状态
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
//当状态为0的时候获取锁,CAS操作成功,则state状态为1,
@Override
public boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
//释放锁,将同步状态置为0
@Override
protected boolean tryRelease(int releases) {
if (getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}
//同步对象完成一系列复杂的操作,我们仅需指向它即可
private final Sync sync = new Sync();
//加锁操作,代理到acquire(模板方法)上就行,acquire会调用我们重写的tryAcquire方法
public void lock() {
sync.acquire(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
//释放锁,代理到release(模板方法)上就行,release会调用我们重写的tryRelease方法。
public void unlock() {
sync.release(1);
}
public boolean isLocked() {
return sync.isHeldExclusively();
}
}

@Test
public void Test02() {
Mutex mutex = new Mutex();

Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is trying to lock...");
mutex.lock();
try {
System.out.println(Thread.currentThread().getName() + " has locked.");
// 模拟一些需要同步执行的任务
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
System.out.println(Thread.currentThread().getName() + " is unlocking.");
mutex.unlock();
}
};

Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");

thread1.start();

thread2.start();

// 确保thread1先运行并获取锁
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
运行结果

Thread-1 is trying to lock…
Thread-2 is trying to lock…
Thread-1 has locked.
Thread-1 is unlocking.
Thread-2 has locked.
Thread-2 is unlocking.

// 注意:也能是Thread-2 先获取到锁

3. 继承AQS实现自定义同步类之二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 演示wait notify 
class BooleanLatch {
private class Sync extends AbstractQueuedSynchronizer {
boolean isSignalled() { return getState() != 0; }
protected int tryAcquireShared(int ignore) {
return isSignalled() ? 1 : -1;
}
protected boolean tryReleaseShared(int ignore) {
setState(1);
return true;
}
}
private final Sync sync = new Sync();
public boolean isSignalled() {
return sync.isSignalled();
}
public void signal() {
sync.releaseShared(1);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
}


@Test
public void Test() throws InterruptedException {
BooleanLatch latch = new BooleanLatch();

// 创建一个线程来等待信号
Thread waiterThread = new Thread(() -> {
System.out.println("Waiter thread is waiting...");
try {
latch.await();
System.out.println("Waiter thread has been signalled!");
} catch (InterruptedException e) {
System.out.println("Waiter thread was interrupted.");
}
});

// 启动等待线程
waiterThread.start();

// 主线程休眠一段时间,模拟一些工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

// 发送信号
System.out.println("Main thread is signalling...");
latch.signal();

// 等待等待线程结束
try {
waiterThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

// 检查信号状态(仅用于演示)
System.out.println("Latch signalled state: " + latch.isSignalled());
}
运行结果

Waiter thread is waiting…
Main thread is signalling…
Waiter thread has been signalled!
Latch signalled state: true


本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.