3.线程的同步互斥与通信
2017-03-22 10:33
197 查看
一、使用synchronized代码块及其原理
二、使用synchronized方法
三、分析静态方法所使用的同步监视器对象是什么?
二、使用synchronized方法
三、分析静态方法所使用的同步监视器对象是什么?
/** * 多线程应用:两个线程对同一个对象(数据)进行操作,就会出现线程安全的问题 * 线程问题:银行转账 * * 总结:互斥的关键字是 synchronized,必须用同一把锁挡住线程,否则线程不同步。 */ public class TraditionalThreadSynchronized1 { public static void main(String[] args) { new TraditionalThreadSynchronized1().init(); } private void init(){ /** * 内部类不能访问局部变量,为了能够访问局部变量要加final * 在静态方法中不能 new 内部类的实例对象,必须先创建外部类的实例对象,才能创建内部类的实例对象 */ final Output outputer = new Output(); //线程A new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangxiaoxiang"); } } }).start(); //线程B new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } /** * new Output().output("lihuoming"); * 不能传入上面的这种形式,因为锁必须传入同一个对象 */ outputer.output2("lihuoming"); } } }).start(); //线程C new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } /** * new Output().output("lihuoming"); * 不能传入上面的这种形式,因为锁必须传入同一个对象 */ outputer.output3("lihuoming"); } } }).start(); } //内部类,加了 static 就相当于外部类 static class Output{ /** * 因为A线程用的outputer对象,B线程用的outputer对象, * 所以可以在Output类里面定义一个变量传入到synchronized中 * synchronized(xxx){} */ //String xxx = ""; //把传入的字符串的字符一个一个的打印在屏幕上 public void output(String name){ int len = name.length(); /** * synchronized(name) * 不能传入name,因为达不到同步的效果(A线程传入的是zhagnxiaoxiang,B传入的是lihuoming),必须要传入同一个对象 */ synchronized(Output.class){ //这段代码要实现原子性,才能保证线程同步,即排他性原理 for(int i=0;i<len;i++){ System.out.print(name.charAt(i)); } System.out.println(); } } /** * ①保护方法的全部代码就在方法上加关键字 synchronized,一个方法上最好用一个 * synchronized,要不然极易出现死锁。 * ②方法上的synchronized就是用的 this对象,所以线程A调用output,线程B * 调用output2,它们用的是同一个监视器对象(同一个门栓),所以有互斥效果。 */ 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(); } /** * 怎么让output3和output同步? * 因为output3是一个静态方法,静态方法要同步,必须要用到锁对象,静态方法运行的时候 * 不用创建类的实例对象,但是静态方法的字节码对象已经在内存里面了,所以在output中传入 * Output.class,就可以实现同步。 * * 重点:静态方法只与字节码对象关联 */ 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(); } } }四、wait与notify实现线程间的通信
/** * 问题: * 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次, * 接着再回到主线程又循环100,如此循环50次,请写出程序。 */ public class TraditionalThreadCommunication { public static void main(String[] args) { final Business business = new Business(); new Thread(new Runnable() { public void run() { for (int i = 1; i <= 50; i++) { business.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { business.main(i); } } } /** * 经验:①要用到的共同数据(包括同步锁)或共同算法的若干个方法应该归在同一个类身上, * 这种设计正好体现了高类聚和程序的健壮性。 * ②锁是上在代表要操作的资源的类的方法中,而不是线程代码中。 * Business业务类(对象),其有两个方法,即主方法和子方法。锁是上在具体资源 (具体干事的)对象的身上, * 线程只是拿着Business对象去运行,所以互斥的问题不是写在线程上的,而是写在线程锁要访问的资源的内部上的, * 这样的好处可以是可以插拔式的运行。 */ class Business { private boolean bShouldSub = true; //子线程 public synchronized void sub(int i) { /** * 如果是主线程,就等待 * while防止伪唤醒,且比if要好 */ while (!bShouldSub) { try { //this作为同步监视器对象 this.wait(); } catch (InterruptedException e) { 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防止伪唤醒,且比if要好 */ while (bShouldSub) { try { //this作为同步监视器对象 this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 100; j++) { System.out.println("main thread sequence of " + j + ",loop of " + i); } bShouldSub = true;//主线程做完轮到子线程 this.notify();//唤醒子线程,因为子线程原先是等待的 } }
相关文章推荐
- Unix,进程,线程,同步,互斥,通信
- 为了在线程间进行可靠的通信,也为了互斥访问,同步是必要的。
- java基础——多线程(线程的同步互斥与通信)
- 3、线程的同步互斥技术和通信
- linux c 线程间同步(通信)的几种方法--互斥锁,条件变量,信号量,读写锁
- Unix,进程,线程,同步,互斥,通信
- java同步和互斥 : 线程之间通信
- java基础——多线程(线程的同步互斥与通信)
- Java同步Socket通信例子(线程方式) ,完整版
- 线程间的通信、同步方式与进程间通信方式
- linux c 线程通信和同步
- 嵌入式系统 - 同步、互斥与通信(上)
- java多线程(三) 线程的同步与通信
- 线程的同步与互斥
- 线程的同步与通信
- Android进程线程之同步互斥(一)
- linux内核中多进程(线程)间同步和互斥
- Linux之线程:同步与互斥
- Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)
- java线程的同步互斥和通讯