欢迎来到天天文库
浏览记录
ID:33471109
大小:125.00 KB
页数:26页
时间:2018-05-25
《java程序设计教程课件-第23章java视频教程-多线程程序设计》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、第23讲多线程同步线程并发引发的问题线程同步原理同步方法与同步语句块控制线程的执行顺序-线程间交互线程同步带来的问题-死锁与效率降低1线程并发引起的问题多个线程相对执行的顺序是不确定的。线程执行顺序的不确定性会产生执行结果的不确定性。在多个线程对共享数据操作时常常会由于这种不确定性而产生错误。2线程并发引起的问题实例一个堆栈类:publicclassMyStack{privateintidx=0;privatechar[]data=newchar[6];publicvoidpush(charc){data[idx]=c;idx++;//栈顶指针指向下一个空单元}publicc
2、harpop(){idx--;returndata[idx];}}3线程并发引起的问题实例线程a和线程b共享堆栈s线程a线程b堆栈s状态时刻t1时刻t2时刻t3//调用s.Push(‘r’);data[idx]=‘r’;//调用s.pop()idx--;returndata[idx];//恢复运行idx++;/*线程a被抢占idx++;未执行*/
3、p
4、q
5、
6、
7、
8、
9、idx=2
10、p
11、q
12、r
13、
14、
15、
16、idx=2
17、p
18、q
19、r
20、
21、
22、
23、idx=1
24、p
25、q
26、r
27、
28、
29、
30、idx=2...效果:“q”被两次压栈;线程a压入的数据“r”丢失!4线程并发引起的问题:实例二publicclassErro
31、rSumThreadextendsThread{publicstaticintsumData=0;publicstaticinttimes=10000;publicintID;publicbooleandone=false;publicErrorSumThread(intid){ID=id;}publicvoidrun(){intd=((ID%2==0)?1:-1);System.out.println("运行线程"+ID+",每次将"+d+"累加到sumData。");for(inti=0;i32、+=d;done=true;System.out.println("结束线程"+ID);}5线程并发引起的问题:实例二publicstaticvoidmain(String[]args){ErrorSumThreadt1=newErrorSumThread(1);ErrorSumThreadt2=newErrorSumThread(2);t1.start();t2.start();System.out.println(Integer.MAX_VALUE);while(!t1.done33、34、!t2.done);System.out.println("sumData="+sumDa35、ta);}}如果不出问题,sumDate最后应该为0,查看实际结果6线程并发执行产生问题的原因各个线程对共享数据的访问被不合理的打断。例一中:两个线程共享一个堆栈对象,则一个线程的进栈操作语句:data[idx]=c;idx++不应该被另一个线程与之相关的操作打断。例二中:两个线程共享数据sumData,则一个线程取sumData和将sumData增加一个量d的操作序列不应该被另一个线程访问sumData的操作打断。解决办法:让线程的访问共享数据的操作序列不被打断,即让这些操作序列“串行”执行。这种方法就叫做线程同步。7线程同步:对象锁对象锁:Java中每个对象(类对象和实例36、对象)都带有一个对象锁(monitor标志)。对象锁是独占排它锁,即一个线程获得这个锁后,其他线程将无法再获得这个锁,直到该对象锁被释放。8多线程同步的原理:对象锁、等待池与同步语句块对象锁与等待池Java中每个对象都带有一个对象锁和一个等待池。这里的对象包括类对象和实例对象。类对象的引用可以通过静态方法Class.forName(“类名”)获得。同步语句块不希望其执行过程被打断的一段代码或一个方法。如堆栈入栈操作的两个语句:data[idx]=c;idx++;或者整个入栈方法。一个同步语句块总是和某个对象相关联。9多线程同步的原理:对象锁与同步语句块同步语句块和同一个对象相37、关联的多个同步语句块(方法),在一个时刻只能有一个执行,且其执行不会被打断。这是通过对象锁机制实现的:a线程要执行某个同步语句块,必须首先获得与该同步语句块相关联的对象锁,由于对象锁具有独占性,a线程获得对象锁后,b线程便不能获得,此时b线程处于阻塞态,直到a线程执行完同步语句块后释放该对象锁,b线程才能根据JVM的调度获得该对象锁。10多线程同步的原理:对象锁与同步语句块同步语句块定义同步语句块的格式为:synchronized(引用类型表达式){语句序列}引用类型表达式定义了与该同步语句块相关联的对
32、+=d;done=true;System.out.println("结束线程"+ID);}5线程并发引起的问题:实例二publicstaticvoidmain(String[]args){ErrorSumThreadt1=newErrorSumThread(1);ErrorSumThreadt2=newErrorSumThread(2);t1.start();t2.start();System.out.println(Integer.MAX_VALUE);while(!t1.done
33、
34、!t2.done);System.out.println("sumData="+sumDa
35、ta);}}如果不出问题,sumDate最后应该为0,查看实际结果6线程并发执行产生问题的原因各个线程对共享数据的访问被不合理的打断。例一中:两个线程共享一个堆栈对象,则一个线程的进栈操作语句:data[idx]=c;idx++不应该被另一个线程与之相关的操作打断。例二中:两个线程共享数据sumData,则一个线程取sumData和将sumData增加一个量d的操作序列不应该被另一个线程访问sumData的操作打断。解决办法:让线程的访问共享数据的操作序列不被打断,即让这些操作序列“串行”执行。这种方法就叫做线程同步。7线程同步:对象锁对象锁:Java中每个对象(类对象和实例
36、对象)都带有一个对象锁(monitor标志)。对象锁是独占排它锁,即一个线程获得这个锁后,其他线程将无法再获得这个锁,直到该对象锁被释放。8多线程同步的原理:对象锁、等待池与同步语句块对象锁与等待池Java中每个对象都带有一个对象锁和一个等待池。这里的对象包括类对象和实例对象。类对象的引用可以通过静态方法Class.forName(“类名”)获得。同步语句块不希望其执行过程被打断的一段代码或一个方法。如堆栈入栈操作的两个语句:data[idx]=c;idx++;或者整个入栈方法。一个同步语句块总是和某个对象相关联。9多线程同步的原理:对象锁与同步语句块同步语句块和同一个对象相
37、关联的多个同步语句块(方法),在一个时刻只能有一个执行,且其执行不会被打断。这是通过对象锁机制实现的:a线程要执行某个同步语句块,必须首先获得与该同步语句块相关联的对象锁,由于对象锁具有独占性,a线程获得对象锁后,b线程便不能获得,此时b线程处于阻塞态,直到a线程执行完同步语句块后释放该对象锁,b线程才能根据JVM的调度获得该对象锁。10多线程同步的原理:对象锁与同步语句块同步语句块定义同步语句块的格式为:synchronized(引用类型表达式){语句序列}引用类型表达式定义了与该同步语句块相关联的对
此文档下载收益归作者所有