目录
一、死锁
死锁的概念:多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致多个线程都在等待对方释放资源,而都停止执行的现象。
某一个同步块同时拥有"两个以上对象的锁"时,就可能发生“死锁”的问题。
死锁示例
package Thread;
/*
* 死锁现象
* */
public class DeadLock {
public static void main(String[] args) {
MakeUp gir1 = new MakeUp(0,"小蒋");
MakeUp gir2 = new MakeUp(1,"小机智");
gir1.start();
gir2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
class MakeUp extends Thread{
static Lipstick lipstick = new Lipstick(); //静态只有一份对象
static Mirror mirror = new Mirror();
int choice;
String girl;
public MakeUp(int choice,String girl) {
this.choice = choice;
this.girl = girl;
}
@Override
public void run() {
//化妆
makeup();
}
//相互持有对方的对象锁,可能造成死锁
private void makeup(){
if(choice==0){
synchronized (lipstick){
System.out.println(this.girl+"获得口红");
//1秒后想拥有镜子的锁
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.girl+"获得镜子");
}
}
}else{
synchronized (mirror){
System.out.println(this.girl+"获得镜子");
//2秒后想拥有口红的锁
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(this.girl+"获得口红");
}
}
}
}
}
避免死锁
package Thread;
/*
* 解除死锁现象-避免锁套锁
* */
public class DeadLock {
public static void main(String[] args) {
MakeUp gir1 = new MakeUp(0,"小蒋");
MakeUp gir2 = new MakeUp(1,"小机智");
gir1.start();
gir2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
class MakeUp extends Thread{
static Lipstick lipstick = new Lipstick(); //静态只有一份对象
static Mirror mirror = new Mirror();
int choice;
String girl;
public MakeUp(int choice,String girl) {
this.choice = choice;
this.girl = girl;
}
@Override
public void run() {
//化妆
makeup();
}
//避免锁套锁!一个锁中尽量不要有第二个锁,可以两个锁并列。
private void makeup(){
if(choice==0){
synchronized (lipstick){
System.out.println(this.girl+"获得口红");
//1秒后想拥有镜子的锁
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (mirror){
System.out.println(this.girl+"获得镜子");
}
}else{
synchronized (mirror){
System.out.println(this.girl+"获得镜子");
//2秒后想拥有口红的锁
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lipstick){
System.out.println(this.girl+"获得口红");
}
}
}
}
二、线程协作-生产者消费者模式理论
生产者消费者模式主要解决的是线程通信问题
生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
强调: wait() 会释放锁!
三、管程法
四个类:生产者、消费者、缓冲区、馒头
package cooperation;
/*
* 协作模型:生产者消费者实现
* 管程法
* */
public class CoTest01 {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Productor(container).start();
new Consumer(container).start();
}
}
//生产者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container) {
this.container = container;
}
@Override
public void run() {
//生产
for(int i=0;i<15;i++){
//生产馒头时间
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
container.push(new Steamedbun(i));
System.out.println("生产 第 "+i+" 个馒头");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
//消费
for(int i=0;i<15;i++){
//消费者购买馒头时间
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费 第 "+container.pop().getId()+" 个馒头");
}
}
}
//缓冲区
class SynContainer{
Steamedbun[] buns = new Steamedbun[10]; //数组长度等于10,0-9
int count = 0; //计数器
//存储(生产)
public synchronized void push(Steamedbun bun){
//有空间的时候才可以生产
if(count == buns.length){
try {
this.wait(); //线程阻塞,消费者通知生产时接触阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buns[count] = bun;
count++;
this.notifyAll(); //目的:唤醒消费的wait
}
//获取(消费)
public synchronized Steamedbun pop(){
//有货的时候才可以消费
if(count==0){
try {
this.wait(); //线程阻塞,生产者通知消费者时接触阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
Steamedbun bun = buns[count];
this.notifyAll(); //目的:唤醒生产的wait
return bun;
}
}
//馒头
class Steamedbun{
private int id;
public Steamedbun(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
四、信号灯法
红绿灯用真假表示
package cooperation;
/*
* 协作模型:生产者消费者实现
* 红绿灯法
* */
public class CoTest02 {
public static void main(String[] args) {
Tv tv = new Tv();
new Player(tv).start();
new Watcher(tv).start();
}
}
//生产者 演员
class Player extends Thread{
Tv tv;
public Player(Tv tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i=0;i<20;i++){
if(i%2==0){
this.tv.play("奇葩说");
}else{
this.tv.play("广告广告");
}
}
}
}
//消费者 观众
class Watcher extends Thread{
Tv tv;
public Watcher(Tv tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i=0;i<20;i++){
tv.watch();
}
}
}
//同一个资源 电视
class Tv{
String voice;
//信号灯
//T 表示演员表演,观众等待
//F 表示观众观看,演员等待
boolean flag = true;
//表演
public synchronized void play(String voice){
//演员等待
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("表演了: "+voice);
this.voice = voice;
//唤醒观众
this.notifyAll();
this.flag=!this.flag;
}
//观看
public synchronized void watch(){
//观众等待
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("听到了: "+voice);
this.notifyAll();
this.flag=!this.flag;
}
}