代码:chapter7
注意一个原则,锁是加在具体的实现的方法里面的,目的是锁方法里面的共享变量的。
---------------------------------21-------------------------------this锁-----------------
代码:
总结:
synchronized代码块自带锁括号里面东西。
---------------------------------------22---------------------------------class锁----------------
代码:chapter8
原因:现在是持有d锁,去等待s释放。持有s锁,等待d释放,就死锁了,如何检测呢?
jstack 进程号
等待池和锁池:https://www.xttblog.com/?p=3294
-------------------------------------23--------------死锁的分析-----------------------------
代码:chapter9
a去数据库拿数据,b线程去展示。
线程之间的通信最典型的就是生产者和消费者。
第一个版本:消费者只能消费最新的,就是因为线程之间没有通信造成的。
可知消费者停留的时间短,消费的多,只消费最新的,而且会消费好多次的。
package one.chapter9;
public class ProduceConsumerVersion1 {
private int i = 1;
final private Object LOCK = new Object();
private void produce() throws InterruptedException {
Thread.sleep(1_000);
synchronized (LOCK) {//在生产的时候是不能消费的
if(i>=10){
return;
}
System.out.println("P->" + (i++));
}
}
private void consume() throws InterruptedException {
Thread.sleep(1_00);
synchronized (LOCK) {
if(i>=10){
return;
}
System.out.println("C->" + i);
}
}
public static void main(String[] args) {
ProduceConsumerVersion1 pc = new ProduceConsumerVersion1();
new Thread("P") {
@Override
public void run() {
while (true) {
try {
pc.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread("C") {
@Override
public void run() {
while (true) {
try {
pc.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
第二个版本:生产完毕通知,不消费就不生产。注意下面的多个生产者消费者会出现问题。
类似于快递公司流水线一个传送带。传送带上有数据就去拿数据,没有数据就等。
不卡死的生产者和消费者,多线程会卡死的:
package one.chapter9;
import java.util.stream.Stream;
public class ProduceConsumerVersion2 {
private int i = 0;
final private Object LOCK = new Object();
private volatile boolean isProduced = false;
public void produce() {
synchronized (LOCK) {
if (isProduced) {
try {
LOCK.wait();//没有消费就一直wait了,再生产就多了 释放锁进入到阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
i++;
System.out.println("P->" + i);
LOCK.notify();//通知消费者消费
isProduced = true;//生产完毕
}
}
}
public void consume() {
synchronized (LOCK) {
if (isProduced) {//已经生产了
System.out.println("C->" + i);
LOCK.notify();//通知生产者生产
isProduced = false;//没有生产了
} else {
try {
LOCK.wait();//没生产等待生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();//这个会卡死的
// Stream.of("P1", "P2").forEach(n ->
// new Thread(n) {
// @Override
// public void run() {
// while (true)
// pc.produce();
// }
// }.start()
// );
// Stream.of("C1", "C2").forEach(n ->
// new Thread(n) {
// @Override
// public void run() {
// while (true)
// pc.consume();
// }
// }.start()
// );
new Thread(){
@Override
public void run() {
while(true){
pc.produce();
}
}
}.start();
new Thread(){
@Override
public void run() {
while(true){
pc.consume();
}
}
}.start();
}
}
package chapter9;
import java.util.stream.Stream;
public class ProduceConsumerVersion2 {
private int i = 0;
final private Object LOCK = new Object();
private volatile boolean isProduced = false;
public void produce() {
synchronized (LOCK) {
if (isProduced) {
try {
LOCK.wait();//没有消费就一直wait了,再生产就多了
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
i++;
System.out.println("P->" + i);
LOCK.notify();//通知消费者消费
isProduced = true;//生产完毕
}
}
}
public void consume() {
synchronized (LOCK) {
if (isProduced) {//已经生产了
System.out.println("C->" + i);
LOCK.notify();//通知生产者生产
isProduced = false;//没有生产了
} else {
try {
LOCK.wait();//没生产等待生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();
Stream.of("P1", "P2").forEach(n ->
new Thread(n) {
@Override
public void run() {
while (true)
pc.produce();
}
}.start()
);
Stream.of("C1", "C2").forEach(n ->
new Thread(n) {
@Override
public void run() {
while (true)
pc.consume();
}
}.start()
);
}
}
此程序是多个生产者和消费者是有问题的:
卡住了。没有死锁的。
为什么,就是c消费了,但是notify了c,c起来看没有物品,就wait了。所有的都wait老了。
--------
问题:p1生产了wait,p2起来看生产了wait了。c1起来了消费了,notify了c2,起来了看没有就wait了。就都wait了。
这个只是唤醒随机的单独的线程的。
wait和notify。wait就是放弃执行权,为block状态。这个是官方的。
网址:https://www.cnblogs.com/hoojjack/p/7932107.html
-----------------------------24---------25----------------线程间的通信---------------
wait就是加入到lock锁的wait队列里面了。
FIFO可能 可能是随机的 或者栈 jvm没有明确的要求。
notify all是同一个的monitor的waiting全部唤醒的。
第三个版本:
package chapter9;
import java.util.stream.Stream;
public class ProduceConsumerVersion3 {
private int i = 0;
final private Object LOCK = new Object();
private volatile boolean isProduced = false;
public void produce() {
synchronized (LOCK) {
while (isProduced) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
System.out.println("P->" + i);
LOCK.notifyAll();
isProduced = true;
}
}
public void consume() {
synchronized (LOCK) {
while (!isProduced) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C->" + i);
LOCK.notifyAll();
isProduced = false;
}
}
public static void main(String[] args) {
ProduceConsumerVersion3 pc = new ProduceConsumerVersion3();
Stream.of("P1", "P2", "P3").forEach(n ->
new Thread(n) {
@Override
public void run() {
while (true) {
pc.produce();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start()
);
Stream.of("C1", "C2", "C3", "C4").forEach(n ->
new Thread(n) {
@Override
public void run() {
while (true) {
pc.consume();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start()
);
}
}
用notifyAll(),不是单个的唤醒的,要用这个。
wait()方法调用,就释放锁。
代码:
注意这个wait方法,wait之后就是放弃了锁,直到被唤醒。
线程的状态:https://www.runoob.com/note/34745
---
为什么是while不是if?
每次跳出都要判断的。
------------26------多Produce多Consume之间的通讯导致出现程序假死的原因解决---------------