线程的互斥与同步通信

当多个线程同时操作同一个对象会出现线程安全问题

1.使用synchronized代码块及其原理

2.使用synchronized方法

3.分析静态方法所使用的同步监视器对象是什么?

4.wait与notify实现线程间的通信

--》用面试宝典中的子线程循环10次和主线程循环5次,两种交替运行

       50次的例子进行讲解。(要用到共同数据包括同步锁的若干个方法应该

       归在同一个类身上,这种设计正好体现了高类聚和程序的健壮性。)


下面用代码的形式讲解上面的知识点:

package thread;

public class SynchronizedTest {
 
    private void init() {
        final Outputer outputer =new Outputer();
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output("xiaoming");
                   }
                }
            }).start();    
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output("yeyongli");
                   }
                }
            }).start();        
    
    }
    
     public static void main(String[] args) {
        new  SynchronizedTest().init();
    }
    
    class Outputer{
        public void output(String name){
            int len=name.length() ;
            for (int i=0; i<len;i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println();
        }
    }
}
上面代码很简单开了两个线程,分别打印xiaoming和yeyongli

运行结果:


上面出现了一个奇迹yeyonglixiaoming,它没把yeyongli执行完,cpu就切换到xiaoming的线程上去了,虽然这种是小概率事件,但是我们也要处理。

我们只要实现output的原子性,当A执行打印代码的时候,其他的线程就在外面等着,等我执行完才能进来,这就是排它性,

只要修改打印的类如下:

    class Outputer{
        String xxx ="";
        public void output(String name){
            int len=name.length() ;
            synchronized (xxx) {
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
            }
        
        }
    }

把要运行的代码用synchronized包起来,就能实现同步,不管是A线程还是B线程来调用这个方法都是用一个XXX就好比是同一把锁,程序运行不敢保证没有问题,但是我敢保证你找不出错误来。xxx变量其实可以写成this,this只被调用的对象,他们调用的都是同一个对象


package thread;

public class SynchronizedTest {
 
    private void init() {
        final Outputer outputer =new Outputer();
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output("xiaoming");
                   }
                }
            }).start();    
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output2("yeyongli");
                   }
                }
            }).start();        
    
    }
    
     public static void main(String[] args) {
        new  SynchronizedTest().init();
    }
    
    class Outputer{
        String xxx ="";
        public void output(String name){
            int len=name.length() ;
            synchronized (this) {
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
            }
        
        }
        
        public  synchronized void output2(String name){
            int len=name.length() ;
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
        }
        
    }
}

锁还能加在方法上实现的效果和代码里是相同的,现在做了改进,第一个线程调用的output方法,

第二个线程是调用output2方法,这两个线程能实现互斥吗?

答案是能实现的,因为他们用的都是同一个监视器对象,所以他们有互斥效果。


package thread;

public class SynchronizedTest {
 
    private void init() {
        final Outputer outputer =new Outputer();
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output("xiaoming");
                   }
                }
            }).start();    
         new Thread(new Runnable() {
                @Override
                public void run() {
                   while(true) {                
                       try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                         e.printStackTrace();
                    }
                       outputer.output3("yeyongli");
                   }
                }
            }).start();        
    
    }
    
     public static void main(String[] args) {
        new  SynchronizedTest().init();
    }
    
    static class Outputer{
        String xxx ="";
        public void output(String name){
            int len=name.length() ;
            synchronized (this) {
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
            }
        }
        public  synchronized void output2(String name){
            int len=name.length() ;
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
        }
        
        
        public static synchronized void output3(String name){
            int len=name.length() ;
                for (int i=0; i<len;i++) {
                    System.out.print(name.charAt(i));
                }
                System.out.println();        
        }
    }
}

运行结果:




运行结果不同步,如何让output和output3同步呢?

我们只要把output3的this改成Output.class就行

因为output3是静态方法,它运行的时候肯定对应一个锁对象,

静态方法运行的时候不会创建一份类的对象,对应的对象就是字节码对象,

字节码对象也是不用创建的,所以两个线程就可以同步了。

以下是最后一个面试题的代码:
import java.util.concurrent.atomic.AtomicInteger;

public class TraditionalThreadCommunication {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        final Business business = new Business();
        new Thread(
                new Runnable() {
                    
                    @Override
                    public void run() {
                    
                        for(int i=1;i<=50;i++){
                            business.sub(i);
                        }
                        
                    }
                }
        ).start();
        
        for(int i=1;i<=50;i++){
            business.main(i);
        }
        
    }

}
  class Business {
      private boolean bShouldSub = true;
      public synchronized void sub(int i){
          while(!bShouldSub){
              try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
          }
            for(int j=1;j<=10;j++){
                System.out.println("sub thread sequence of " + j + ",loop of " + i);
            }
          bShouldSub = false;
          this.notify();
      }
      
      public synchronized void main(int i){
              while(bShouldSub){
                  try {
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
              }
            for(int j=1;j<=100;j++){
                System.out.println("main thread sequence of " + j + ",loop of " + i);
            }
            bShouldSub = true;
            this.notify();
      }
  }
























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值