皮皮安学Java第三十一天(线程解决)

四、线程安全

1.简介
多个线程同时访问共享数据时可能会出现的问题,称为线程安全问题。
当多线程访问共享数据时,由CPU切换,导致一个线程只执行了关键代码的一部分,还未执行完。
此时另一个线程参与进来,导致共享数据发生异常。

解决
线程同步机制synchronized + 锁
被synchronized包裹的代码块,称为同步代码块
被synchronized修饰的方法,称为同步方法
锁,也称为对象锁,每个对象都自带又一个锁(标识),且不同对象的锁是不一样的。
静态方法,使用的是当前类的Class对象的锁

执行过程:
当线程执行同步代码块和同步方法时,必须获取特定对象的锁才行。
且一旦对象的锁被获取,则该对象就不在拥有锁,直到线程执行完,同步代码块或同步方法时,才会释放对象的锁。
如果线程无法获取特定对象的锁,则线程会进入该对象的锁池中等待,直到锁被归还对象,此时需要锁的线程进行竞争。
只需要将关键字代码放到synchronized块中,不要将run()方法中所有都添加进去,否则相当于单线程。

线程同步的优缺点:
优点:解决线程安全的问题,使代码块在某一个时间只能被一个线程访问。
缺点:由于需要进行锁的判断,消耗资源,效率变低。

五、线程间的通信

1.锁池和等待池
每个对象都自带锁池和等待池
锁池
当线程执行synchronized块时,如果无法获取特定对象上的锁,则会进入该对象的锁池。
当锁被归还给对象时,锁池中的多个对象会竞争该对象的锁。
获取对象锁的线程将执行synchronized块,执行完毕后释放锁。
等待池
当线程获取对象锁后,可以调用wait()方法放弃锁,此时会进入该对象的等待池。
当其他此线程调用该对象的notify()或notifyAll()方法等待池中的线程会被唤醒,会进入该对象的锁池。
当线程获取对象的锁后,将从它上次调用wait()方法的位置开始继续运行。

2.相关方法

	方法名			作用																		说明
	wait				使用线程放弃对象锁,线程进入等待池				可以调用等待超时,超时后线程自动唤醒
	notify()			随机唤醒等待池中的一个线程,线程进入锁池	唤醒的是特定对象的等待池中的线程
	notifyAll()		唤醒等待池中所有的线程
	注意:这三个方法都只能在synchronized块使用,即使只有获取了锁的线程才能调用。
			   等待和唤醒必须使用的是同一个对象

生产者-消费者问题

这里吐槽一下,是不是瞬间回到了高中生物???

1.简介
生产者-消费者问题是多线程同步的一个经典问题,即并发协作问题。
主要包含了两种线程:生产者线程,消费者线程。

生产者线程
生产商品并放入缓冲区
当缓冲区满时,生产者不可生产商品。

消费者线程
从缓冲区取出商品
当缓冲区为空时,消费者不可再取出商品。

注:生产者和消费者公用一个缓冲区。

七、线程单例

1.简介
为每个线程提供一个实例。
同一个线程获取的是一个实例。
不同线程获取的是不同的实例。

Java中提供了一个ThreadLocal,直接提供了线程单例的解决方案。
用于管理变量,提供了线程局部变量。
它为变量在每个线程中都存储了一个本地副本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值