并发编程 并发编程第四章共享模型之管程(悲观锁)

主要课程的部分内容

并发编程 并发编程第四章共享模型之管程(悲观锁)_第1张图片

 多线程共享cpu出现的问题:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第2张图片

 并发编程 并发编程第四章共享模型之管程(悲观锁)_第3张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第4张图片

 出现问题的原因是,每次的加操作不是一条指令,而是多条指令,如果是多条指令的话就有可能被打断,并且篡改变量的值。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第5张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第6张图片

 共享资源读的时候是没问题的,写的时候是有问题。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第7张图片

如何避免竞争状态?

并发编程 并发编程第四章共享模型之管程(悲观锁)_第8张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第9张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第10张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第11张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第12张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第13张图片

第一个问题,如果是放在外面就是让五千行代码执行完之后再执行别的线程的代码

第二个问题,两个保护的是两个对象,这样的话就无法保证一个资源同一时间内只有一个线程在使用。

第三个问题:不可以,要对临界区进行保护,需要对使用这个对象的所有的线程都加锁。

锁对象面向对象升级:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第14张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第15张图片

方法上的synchronized关键字:加在方法上也是要锁对象或者是锁住类。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第16张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第17张图片

线程八锁

第一问:这题考察的是线程和线程之间没有串行关系,有可能第二个线程先抢到时间怕片:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第18张图片

第二问:看哪个线程先抢到时间片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第19张图片

第三问:由于第三个线程没加锁,3是并行执行的。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第20张图片

第四问:这道题的加锁的两个对象不同,所以还是要并行执行。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第21张图片

第五问:这里的两个方法一个有static一个没有static因此一个锁对象,一个锁类对象,所以两个还是并行执行。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第22张图片

第六问:锁住同一个对象,两个线程争抢时间片。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第23张图片

第七问:并行执行

并发编程 并发编程第四章共享模型之管程(悲观锁)_第24张图片

第八问:锁住同一个类对象所以只能同一时间执行一个。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第25张图片

4.4变量的线程安全分析

并发编程 并发编程第四章共享模型之管程(悲观锁)_第26张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第27张图片

成员变量不安全的例子

并发编程 并发编程第四章共享模型之管程(悲观锁)_第28张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第29张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第30张图片

解决方法

并发编程 并发编程第四章共享模型之管程(悲观锁)_第31张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第32张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第33张图片

答案:不会出现线程安全的问题。

但是如果添加子类会出现线程安全的问题。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第34张图片

下面的get和put两个方法组合起来就不是安全的了。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第35张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第36张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第37张图片

观看两个线程不安全的例子

这个例子里的成员变量count可能会被多个线程同时修改。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第38张图片

 这个例子中的AOP过程中单例的成员变量是被共享的。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第39张图片

这个例子虽然有成员变量,但是因为成员变量是私有的,并且成员变量指向的类没有成员变量,所以这个例子也是线程安全的

并发编程 并发编程第四章共享模型之管程(悲观锁)_第40张图片

这个例子是线程不安全的以为conn变量是被共享的应该写成是局部变量

并发编程 并发编程第四章共享模型之管程(悲观锁)_第41张图片

这里的例子是线程安全的,因为每个对象单独创建了一个UserDao对象,就不存在多个线程同时争夺一个成员变量的问题:

4.6 Monitor概念

并发编程 并发编程第四章共享模型之管程(悲观锁)_第42张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第43张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第44张图片 并发编程 并发编程第四章共享模型之管程(悲观锁)_第45张图片

Synchronized是如何实现的

首先当一个对象obj加锁之后,obj的markword会指向操作系统中的monitor,一个线程Thread-2占据这个锁,此时这个线程就会占有owner,这时如果又来了其他线程EntryList会指向后来的线程进行等待,后面的线程进入了阻塞状态。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第46张图片并发编程 并发编程第四章共享模型之管程(悲观锁)_第47张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第48张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第49张图片

 通过交换锁记录地址可以让对象知道哪个线程锁住了他。cas是原子性的锁交换操作。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第50张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第51张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第52张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第53张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第54张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第55张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第56张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第57张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第58张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第59张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第60张图片

 撤销偏向锁:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第61张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第62张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第63张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第64张图片

 锁消除:当加不加锁效果一致的时候就要进行锁消除。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第65张图片

wait和notify

并发编程 并发编程第四章共享模型之管程(悲观锁)_第66张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第67张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第68张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第69张图片

wait和notify的正确使用方法

并发编程 并发编程第四章共享模型之管程(悲观锁)_第70张图片并发编程 并发编程第四章共享模型之管程(悲观锁)_第71张图片

这里注意notify只能随机唤醒一个线程,而不是挑一个指定的线程唤醒。存在唤醒不满足条件的线程称之为虚假线程,所以需要使用waitnotifyall()

并发编程 并发编程第四章共享模型之管程(悲观锁)_第72张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第73张图片

标准的使用notify的格式

并发编程 并发编程第四章共享模型之管程(悲观锁)_第74张图片

模式之保护性暂停

并发编程 并发编程第四章共享模型之管程(悲观锁)_第75张图片

 实例:讲一个线程从百度下载的资源传到guardedObject然后再用另外一个线程来接收GuardedObject中的资源,这样的话就可以实现保护性暂停。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第76张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第77张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第78张图片

保护性暂停之扩展增加时长。

在guardedObject修改等待的时间

并发编程 并发编程第四章共享模型之管程(悲观锁)_第79张图片

join的原理:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第80张图片

 futures的实现:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第81张图片

邮箱类:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第82张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第83张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第84张图片并发编程 并发编程第四章共享模型之管程(悲观锁)_第85张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第86张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第87张图片

异步模式之生产者消费者

并发编程 并发编程第四章共享模型之管程(悲观锁)_第88张图片

 并发编程 并发编程第四章共享模型之管程(悲观锁)_第89张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第90张图片

 测试代码:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第91张图片

4.9park and unpark

使用Locksupport类来调用park和unpark

并发编程 并发编程第四章共享模型之管程(悲观锁)_第92张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第93张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第94张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第95张图片

reentrantlock类似于synchronized关键字:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第96张图片

多个条件变量,相当于是多个waitset集合。

reentrantlock锁是创建出来的,本身就是一一把锁对象,调用reentrantlock对象.lock()的方式加锁。

并发编程 并发编程第四章共享模型之管程(悲观锁)_第97张图片

不同于synchronized关键字,这里的临界区保护被try块保护起来了,而不是sychronized(对象)的方式进行保护临界区。

条件变量:reentrantlock得多个条件变量:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第98张图片

4.10顺序控制:

保证t1后于t2运行:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第99张图片

实现相同的顺序实现功能:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第100张图片

交替执行,交替输出:

测试代码

并发编程 并发编程第四章共享模型之管程(悲观锁)_第101张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第102张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第103张图片

交替输出实现第二种方法:

并发编程 并发编程第四章共享模型之管程(悲观锁)_第104张图片 

 并发编程 并发编程第四章共享模型之管程(悲观锁)_第105张图片

并发编程 并发编程第四章共享模型之管程(悲观锁)_第106张图片

你可能感兴趣的:(java并发编程,java高并发编程)