多线程与高并发(三)
ReentrantLock
synchronized是可重入锁,ReentrantLock也是可重入锁,reentrantlock用于替代synchronized
由于m1锁定this,只有m1执行完毕的时候,m2才能执行,这里是复习synchronized最原始的语义。
使用reentrantlock可以完成同样的功能
- 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍)!
- 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放
package 多线程与高并发.ReentrantLock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 描述 ReentrantLock
*
* @author lixinzhen
* @create 2022/4/27 1:02
*/
public class T02_ReentrantLock2 {
Lock lock = new ReentrantLock();
void m1() {
try {
lock.lock(); //synchronized(this)
for (int i = 0; i < 10; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
void m2() {
try {
lock.lock();
System.out.println("m2 ...");
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
T02_ReentrantLock2 rl = new T02_ReentrantLock2();
new Thread(rl::m1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(rl::m2).start();
}
}
运行结果:
ReentrantLock vs synchronized
- 使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待
- 使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应, 在一个线程等待锁的过程中,可以被打断
- ReentrantLock还可以指定为公平锁
CountDownLatch
latch.countDown();
latch.await();
CyclicBarrier
有两种实现方式,第二个参数建立在第一个参数之上。只有满了才能发车。
package 多线程与高并发.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 描述 CyclicBarrier
*
* @author lixinzhen
* @create 2022/4/27 1:28
*/
public class T07_TestCyclicBarrier {
public static void main(String[] args) {
//CyclicBarrier barrier = new CyclicBarrier(20);
CyclicBarrier barrier = new CyclicBarrier(20, () -> System.out.println("满人"));
/*CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
@Override
public void run() {
System.out.println("满人,发车");
}
});*/
for(int i=0; i<100; i++) {
new Thread(()->{
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
运行结果
Phaser
字面意思阶段。在用计算机解决达尔文遗传算法问题的时候用得上Phaser。下面举一个婚礼的例子。
static class MarriagePhaser extends Phaser {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
switch (phase) {
case 0:
System.out.println("所有人到齐了!" + registeredParties);
System.out.println();
return false;
case 1:
System.out.println("所有人吃完了!" + registeredParties);
System.out.println();
return false;
case 2:
System.out.println("所有人离开了!" + registeredParties);
System.out.println();
return false;
case 3:
System.out.println("婚礼结束!新郎新娘抱抱!" + registeredParties);
return true;
default:
return true;
}
}
}
ReadWriteLock
ReadWriteLock读写锁,其实就是共享锁和排它锁。
Semaphore
信号量,目的就是限流。
Semaphore s = new Semaphore(i);
s.acquire();
s.release();
Exchanger
两个线程之间交换数据。
LockSupport
让当前线程阻塞。
package 多线程与高并发.LockSupport;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* 描述 LockSupport
*
* @author lixinzhen
* @create 2022/4/27 2:13
*/
public class T13_TestLockSupport {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(i);
if (i == 5) {
LockSupport.park();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
LockSupport.unpark(t);
}
}
运行结果: