java线程深度解析(二)——线程互斥技术与线程间通信
来源:互联网 发布:出库单软件 编辑:程序博客网 时间:2024/06/08 05:53
http://blog.csdn.net/daybreak1209/article/details/51307679
在java多线程——线程同步问题中,对于多线程下程序启动时出现的线程安全问题的背景和初步解决方案已经有了详细的介绍。本文将再度深入解析对线程代码块和方法的同步控制和多线程间通信的实例。
一、再现多线程下安全问题
先看开启两条线程,分别按序打印字符串的实验
1、创建一个Output内部类,并给出根据参数name,循环打印出传入字符串
2、new 两个线程,分别传入zhongailing、max两个name,调用同一个output对象的output方法
摘取部分输入结果如下:
可以看出,打印出来的name名除了zhongailing 和max之外,还出现iling、mzhax之类字样,这是肿么回事?
这是因为两条线程同时调用同一个output对象的output方法,当第一个线程的打印循环还未走完时,下一个线程又进入传入另一个参数继续循环,使得打印出的结果出现iling、mzhax这些非正常字样。
二、解决线程安全问题——设置线程互斥
在java多线程——线程同步问题中已经介绍了使用synchronized关键字对代码块或者整个方法体进行设置,使得该段代码享有排他性,独立占用资源,完成打印循环之后,下个线程再进入。
题外话:客户端使用main方法进行调用时:
在new 内部类 Output是报错,这是因为在静态方法中不能实例化内部类。因为内部类的特点就是可以访问外部类的成员变量,又因为对象创建完了才为成员变量分配空间,所以在使用变量之前,这个类已经实例化了。而静态方法执行时,可以不用创建这个对象就使用而矛盾。并且main这个静态方法在运行时没有使用任何外部类的成员变量,所以要创建内部类的实例对象,必须已经存在外部类的实例对象来创建。代码改造为:使用synchronized需谨慎:
1、对于多个线程的执行对象一定是同一个。例如这里new 同一个Output对象,执行方法,只是方法传入的参数不同。这个应该比较好理解,如果你为当前线程加上互斥方案,但多个线程启用的并不是同一个对象,那无论做多少不同步方案都是无用功,因为压根就没在一个对象中进行多线程处理。
2、该关键字在一段代码里一般只使用一次。打个比方,如果将方法和方法内部的代码块同时加上synchronized关键字,就类似于原本只有一把锁,钥匙给了方法,而代码块也需要这把钥匙开锁执行自己的代码,双方谁也不释放,容易产生死锁问题。
三、多线程间通信
一个实例:两条线程-主线程、子线程,要求子线程先执行10次,主线程再执行100次,整体反复执行50次。
代码思路:
1、首先两条线程互斥,各不影响
2、创建标识,让子线程先执行,主线程等待;当子线程执行完第一个10次循环,改变标识,唤醒主线程执行。
亮点:
将互斥约束到线程资源上,而非线程代码块中:将两条线程代码写到一个innerclass中,在方法上进行同步约束和线程执行等待逻辑操作,而不是直接在main方法new Thread时,对代码块进行互斥。这样无论谁调用线程逻辑,直接调用innerclass(资源的)的sub 和main方法就可满足线程安全要求,更符合面向对象的思想。同时免去了对同对象参数的考虑。
四、总结
一)synchronized是Java语言级别内置的同步机制,根据作用的对象分为:类锁、实例锁;
对于类锁的应用:只能应用到类的静态方法上,形如:staticsynchronized method();
对于实例锁应用:
1、非静态方法:synchronized method();
2、代码块:synchronized{}或synchronized(this){}
3、指定实例:synchronized(Object obj);
非静态方法和代码块使用synchronized的实质都一样,对当前所属类的实例枷锁。而指定实例是对括号里传入的obj对象加锁。如同上面的例子,使用的就是代码块和指定实例对象加锁方式。另外synchronized不能被直接继承。
笔者体会而言, 对于多线程中synchronized的使用,除了它的作用范围定在类上、方法上、对象、代码块这些point之外,还需要注意加锁的对象是否是同一个。例如上面例子如果不加this,哪怕使用了synchronized对于线程安全还是无法保障的。因为线程调用同一对象的output方法,琐是加了,but并未作用于该对象上。
二)多线程间通信wait,notify方法的合理使用,也是线程的重要部分。本文仅提供了一个线程间通信的实例,在接下来的博文将详细介绍线程间通信应用。
- java线程深度解析(二)——线程互斥技术与线程间通信
- java线程深度解析(二)——线程互斥技术与线程间通信
- java中的多线程——线程创建方式、线程互斥和线程间通信
- java基础——多线程(线程的同步互斥与通信)
- java基础——多线程(线程的同步互斥与通信)
- java线程深度解析(六)——线程池技术
- java线程深度解析(六)——线程池技术
- 多线程详细解析(二) 线程的共享互斥与线程的协调
- Java Socket通信技术收发线程互斥的解决方法
- Java线程(一):传统线程的实现、互斥与通信
- 多线程系列二——java线程间的互斥与同步
- Java多线程技术篇--线程的互斥与同步通信
- Java—传统线程互斥技术synchronized
- 【java并发】传统线程互斥技术—synchronized
- 线程:互斥资源与线程间通信(Producter&Comsumer)
- 线程互斥(二)
- 线程的互斥与同步通信
- 线程的互斥与同步通信
- Shell—文件的引入
- Android内存监测工具DDMS->Heap,内存分析工具->MAT
- 387 div2 cf 4
- java线程深度解析(一)——java new 接口?匿名内部类给你答案
- 现在完成时与过去完成时的区别
- java线程深度解析(二)——线程互斥技术与线程间通信
- C
- MT6582编译到preloader报错
- 编写jQueryUI插件(widget)
- WEB
- Linux的shell脚本换行符引起的unexpected syntax errror: ‘最简单方法
- 最短的蛇形填数算法 5个分号 10行!
- chrome浏览器 adobe flash player过期问题
- 编译原理(笔记)