多线程同步互斥实例——使用synchronized实现线程通信和互斥

来源:互联网 发布:敲诈淘宝卖家减肥药 编辑:程序博客网 时间:2024/05/22 02:22

  • 线程互斥概念

      线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

  • 实现线程同步互斥的四种方式

      临界区(Critical Section):适合一个进程内的多线程访问公共区域或代码段时使用

      互斥量 (Mutex):适合不同进程内多线程访问公共区域或代码段时使用,与临界区相似。

      事件(Event):通过线程间触发事件实现同步互斥

      信号量(Semaphore):与临界区和互斥量不同,可以实现多个线程同时访问公共区域数据,原理与操作系统中PV操作类似,先设置一个访问公共区域的线程最大连接数,每有一个线程访问共享区资源数就减一,直到资源数小于等于零。

  • 实例说明线程同步和互斥

      以一道面试题为例:

      子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着在回到主线程循环100次,如此循环50次,请写出程序。

      解题思路:

      由题可知道,需要创建一个程序,然后创建两个线程(new Thread().start();)。在线程中,使用runnable 分别实现循环10次和100次。在将整个程序循环50次。则代码如下:
package cn.itcast.heima2;public class TraditionalThreadCommuniction {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {for (int j = 1; j <= 50; j++) {<span style="font-family: Arial, Helvetica, sans-serif;">//子程序循环50次</span>for (int i = 1; i <= 10; i++) {//执行10次输出子程序System.out.println("sub sthread sequece of " + i+ ",loop of" + j);}}}}).start();for (int j = 1; j <= 50; j++) {//主程序循环50次for (int i = 1; i <= 100; i++) {//执行100次输出主程序System.out.println("main sthread sequece of " + i+ ",loop of" + j);}}}}
      执行结果如下,从结果中,我们可以看到,这并不是我们要的结果。
      
      
      主线程和子线程的执行都被打断了,所以  我们要把中间打印的循环代码保护起来。在这里,我们可以使用锁(synchronized), 实现主线程和子线程互相不被打断。可以使用TraditionalThreadSynchronized.class 。

      则第一步改进代码如下:

package cn.itcast.heima2;public class TraditionalThreadCommuniction {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {for (int j = 1; j <= 50; j++) {synchronized (TraditionThradSynchronized.class) {for (int i = 1; i <= 10; i++) {System.out.println("sub sthread sequece of " + i+ ",loop of" + j);}}}}}).start();for (int j = 1; j <= 50; j++) {synchronized (TraditionThradSynchronized.class) {for (int i = 1; i <= 100; i++) {System.out.println("main sthread sequece of " + i+ ",loop of" + j);}}}}}
      
      生成结果,虽然结果并非我们所期望的结果,但是,从结果中,我们可以看到,主线程和子线程已经实现了独立的执行,但是,并不能保证子线程和主线程交替出现,这怎么解决呢?

      继续改进:

      思路:我们可以把有关联的方法,集中到一个类中,这样是不是更好维护和更改呢?这就是高内聚的思想。即把相关联的方法放到同一个类上。所以,我们可以改造我们的类,生成一个类Business,其拥有两个方法,sub和main。则main方法中,放入主线程互斥的那部分代码;sub中放入子线程的互斥部分代码。然后再程序中分别调用这两个方法。

      在business中,使用synchronized实现两个方法互斥。然后,在实现两个方法的交替出现。即实现主线程和子线程的互相通信。这样就非常简单,我们可以引入一个内部变量,bshouldSub ,如果bshouldSub是true,则执行子线程,否则等待。如果是flase则执行主线程,否则主线程等待。在执行主线程之后,将bshouldSub设置为true,并唤醒等待程序,子线程执行同理。则程序代码如下:
package cn.itcast.heima2;public class TraditionalThreadCommunictionn {public static void main(String[] args) {final Business business= new Business();new Thread(new Runnable() {@Overridepublic void run() {for (int j = 1; j <= 50; j++) {business.sub(j);}}}).start();for (int j = 1; j <= 50; j++) {business.main(j);}}}class Business{private boolean bshouldSub = true;//子线程和主线程通信信号public synchronized void sub(int j){if(!bshouldSub){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 1; i <= 10; i++) {System.out.println("sub sthread sequece of " + i+ ",loop of" + j);}bshouldSub = false;//运行结束,设置值为FALSE 让主程序运行this.notify();//唤醒等待的程序}public synchronized void main(int j){if(bshouldSub){//如果bshouldsub=true ,等待  让子程序运行try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 1; i <= 100; i++) {System.out.println("main sthread sequece of " + i+ ",loop of" + j);}bshouldSub = true;//让子程序运行this.notify();//唤醒等待的一个程序}}

      由此程序,我们可以看到输出的结果为(由于篇幅限制,这里只截几张图来说明结果):
      
        
     
           

  • 总结:     

      要用到共同数据(包括同类锁)或共同算法的若干方法应该归在同一个类身上,这种设计正好体现了高内聚和程序的健壮性。在解决线程的问题时,更多的从面相对象的思想上去思考问题和解决问题,会得到更好的效果。




1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝出生两天了不吃不喝怎么办 八个月宝宝阴唇边红肿痛怎么办 儿童五周岁九个月比同龄矮怎么办 8个月宝宝长牙母乳喂养咬人怎么办 6周的孩子视力低常怎么办 宝宝吃了甜食生痰咳嗽怎么办 两个月的边牧抵抗力差怎么办 阴茎勃起后向上翘的厉害怎么办 5个月宝宝发烧38.5度怎么办 9个月宝宝发烧38.5度怎么办 八个月宝宝只吃母乳不吃奶粉怎么办 八个月母乳不够宝宝不吃奶粉怎么办 八个月宝宝吃母乳不吃奶粉怎么办 八个月宝宝戒奶不吃奶粉怎么办 刚满月的宝宝发烧38度怎么办 未满月的宝宝发烧38度怎么办 半月大的婴儿吃奶就漾奶怎么办 上司交给你不能完成的任务怎么办 电脑光驱里放入光碟放不出来怎么办 黑暗之魂3太难了怎么办 苹果手机下载的游戏闪退怎么办 宝宝两岁了不怎么爱拉大便怎么办? 小狗脖子发硬疼的直叫怎么办 厨房里有很多小虫子围着鸡蛋怎么办 狗生小狗后几天不吃饭怎么办 还没满月的小兔子突然死了怎么办 宝宝小鸡被蚊子咬后肿得很大怎么办 不知道是哪知兔子下的小兔怎么办 兔子生完小兔不吃东西了怎么办 人工喂养七天的小羊拉希怎么办 仔兔出生3天吃过奶就尿怎么办 小兔子买回来两天不拉屎怎么办 大狗生了小狗把小狗咬死了怎么办 狗妈妈一直咬小狗的脐带怎么办 狗狗体内驱虫驱不干净怎么办 打老鼠脚被老鼠咬了怎么办 天正画的cad打开显示空白怎么办 苹果手机信息被拉进群聊怎么办 空调的控制线的报验资料怎么办 窗窗户罩子护栏上的瓦楞板怎么办 酸洗好的带钢容易返锈怎么办