p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解
目录
当一个线程需要获得多把锁的时候,便容易发生死锁
活锁出现在两个线程互相改变对方的结束条件,导致最后谁也无法结束
饥饿,即一个线程由于优先级太低,始终得不到CPU调度执行,也不能结束
ReentrantLock 可重入锁
相对于synchronized它具备如下特点
●可中断
●可以设置超时时间
●可以设置为公平锁(一般没必要,会降低并发度)
●支持多个条件变量
与synchronized一样,都支持可重入
可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住
java
import java.util.concurrent.locks.ReentrantLock;
public class Main {
private static ReentrantLock lock =new ReentrantLock();
public static void main(String[] args) {
lock.lock();
try {
System.out.println("main获得锁");
m1();
}finally {
lock.unlock();
}
}
public static void m1() {
lock.lock();
try {
System.out.println("m1获得锁");
m2();
}finally {
lock.unlock();
}
}
设计模式
固定顺序运行
java
wait-notify形式
public class Main {
//同步
static final Object lock = new Object();
static boolean t2runed = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (lock) {
while (!t2runed) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t1");
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("t2");
t2runed = true;
lock.notify();
}
});
t1.start();
t2.start();
}
}
-----------------------------------------------------------------------------
park-unpark形式
import java.util.concurrent.locks.LockSupport;
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
LockSupport.park();
System.out.println("t1");
});
Thread t2 = new Thread(() -> {
System.out.println("t2");
LockSupport.unpark(t1);
});
t1.start();
t2.start();
}
}
交替输出
java
wait-notify形式
public class Main {
public static void main(String[] args) {
waitNotify wn = new waitNotify(1, 5);
new Thread(()->{
wn.print("a",1,2);
}).start();
new Thread(()->{
wn.print("b",2,3);
}).start();
new Thread(()->{
wn.print("c",3,1);
}).start();
}
}
/*
* 输出内容 等待标记 下一个标记
* a 1 2
* b 2 3
* c 3 1
* */
class waitNotify{
//等待标记
private int flag;
//循环次数
private int loopNumber;
public waitNotify(int flag, int loopNumber) {
this.flag = flag;
this.loopNumber = loopNumber;
}
//打印
public void print(String str,int waitFlag,int nextFlag){
for (int i = 0; i < loopNumber; i++) {
synchronized (this){
while(flag!=waitFlag){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print(str);
flag=nextFlag;
this.notifyAll();
}
}
}
}
await-singal形式
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) {
AwaitSignal as = new AwaitSignal(5);
Condition a = as.newCondition();
Condition b = as.newCondition();
Condition c = as.newCondition();
new Thread(()->{
as.print("a",a,b);
}).start();
new Thread(()->{
as.print("b",b,c);
}).start();
new Thread(()->{
as.print("c",c,a);
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
as.lock();
try{
System.out.println("开始");
a.signal();
}finally {
as.unlock();
}
}
}
class AwaitSignal extends ReentrantLock {
private int loopNumber;
public AwaitSignal(int loopNumber) {
this.loopNumber = loopNumber;
}
public void print(String str, Condition current,Condition next) {
for (int i = 0; i < loopNumber; i++) {
lock();
try {
current.await();
System.out.print(str);
next.signal();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
unlock();
}
}
}
}
park-unpark形式
import java.util.concurrent.locks.LockSupport;
public class Main {
static Thread t1;
static Thread t2;
static Thread t3;
public static void main(String[] args) {
ParkUnpark pu = new ParkUnpark(5);
t1 = new Thread(()->{
pu.print("a",t2);
});
t2 = new Thread(()->{
pu.print("b",t3);
});
t3 = new Thread(()->{
pu.print("c",t1);
});
t1.start();
t2.start();
t3.start();
LockSupport.unpark(t1);
}
}
class ParkUnpark{
private int loopNumber;
public ParkUnpark(int loopNumber){
this.loopNumber = loopNumber;
}
public void print(String str,Thread next){
for(int i=0;i<loopNumber;i++){
LockSupport.park();
System.out.print(str);
LockSupport.unpark(next);
}
}
}