zoukankan      html  css  js  c++  java
  • java线程之——synchronized的注意细节

      我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

      然后就做了个实验(实验代码最后贴出),最后得到了如下结论。

    现在分两种情况来讨论:1.当前线程调用的是synchronized普通方法(相对于static方法);2.当前线程调用的是synchronized static方法。

     1.当前线程调用的是synchronized普通方法(相对于static方法)时,其它线程是否可进入此对象的其它方法:

      1)其它方法是加了synchronized的普通方法,不能;

      2)其它方法是没加synchronized的普通方法,能;

      3)其它方法是synchronizedstatic方法,能;

      4)其它方法是没加synchronizedstatic方法,能。

     2.当前线程调用的是synchronized static方法,其它线程是否可进入此对象的其它方法:

      1)其它方法是加了synchronized的普通方法,能;

      2)其它方法是没加synchronized的普通方法,能;

      3)其它方法是synchronizedstatic方法,不能;

      4)其它方法中有synchronized(xxx.class)的,不能;

      5)其它方法是没加synchronizedstatic方法,能。

      其实只要明白了普通方法加synchronized的本质是给对象的this加了对象锁,上面的结论就不难理解了,

      其中不管static方法是否加synchroized,只要锁的是this,即当前对象,而不是当前类(XXX.class),就可以执行;

      而给当前类加锁时,除了同步的static方法不能调用外,其它的都可以。

      

      实验代码如下:

    package javaBase;
    
    public class JB_052_Synchronized {
    	public static void main(String[] args) {
    		Resource_052 rs = new Resource_052();
    		
    		Thread t1 = new Thread(new Thread1_052(rs));  //调用synchronized方法的线程
    		Thread t0 = new Thread(new Thread0_052(rs));  //调用普通方法的线程
    		Thread t2 = new Thread(new Thread2_052(rs));  //调用另一个synchronized方法的线程
    		Thread t3 = new Thread(new Thread3_052(rs));  //调用synchronized static 方法的线程
    		Thread t4 = new Thread(new Thread4_052(rs));  //调用static方法的线程
    		
    		Thread t5 = new Thread(new Thread5_052(rs));  //调用锁class方法的线程
    		
    		t1.start();  //调用了synchronized方法
    		try{
    			System.out.println("调用synchronized方法的thread1启动后主程序等待2秒,确保在其它线程执行之前thread1获得对象锁");
    			Thread.sleep(2000);
    		}catch(InterruptedException e){
    			e.printStackTrace();
    		}
    		t0.start();   //调用了普通方法  //可以 
    		t2.start();   //调用了另一个synchronized方法   //不行
    		t3.start();   //调用了synchronized static 方法  //可以
    		t4.start();  //调用了static方法   //可以
    		
    		
    		//锁class
    		try{
    			System.out.println("主程序等待10秒,等前面的线程除thread1和被阻塞的线程外都执行完成,后面的代码将做锁class测试....");
    			Thread.sleep(10000);
    			System.out.println("10秒等待完。");
    		}catch(InterruptedException e){
    			e.printStackTrace();
    		}
    		//thread5中会置flag=false终止thread1
    		t5.start();
    		try{
    			System.out.println("主程序等待10秒,确保thread5获得class的对象锁,确保thread1和被阻塞的线程都终止。");
    			Thread.sleep(10000);
    			System.out.println("10秒等待完。");
    		}catch(InterruptedException e){
    			e.printStackTrace();
    		}
    		 
    		t0 = new Thread(new Thread0_052(rs));  //普通方法
    		t2 = new Thread(new Thread2_052(rs));  //另一个synchronized方法
    		t3 = new Thread(new Thread3_052(rs));  //synchronized static 方法
    		t4 = new Thread(new Thread4_052(rs));  //static方法
    		
    		t0.start();   //调用了普通方法  //可以 
    		t2.start();   //调用了另一个synchronized方法   //不行
    		t3.start();   //调用了synchronized static 方法  //不可以
    		t4.start();  //调用了static方法   //可以
    	}
    }
    
    
    class Resource_052{
    	public boolean flag = true;
    	
    	public void method0(){
    		System.out.println("this is a ordinary method——method0.");
    	}
    	synchronized public void method1(){
    		while(flag){
    			System.out.println("this is a synchronized method——method1.");
    			try{
    				Thread.sleep(2000);
    			}catch(InterruptedException e){
    				e.printStackTrace();
    			}
    		}
    	}
    	synchronized public void method2(){
    		System.out.println("this is the second synchronized method——method2.");
    	}
    	synchronized public static void method3(){
    		System.out.println("this is a  synchronized static method——method3.");
    	}
    	public static void method4(){
    		System.out.println("this is a  ordinary static method——method4.");
    	}
    	
    	public void method5(){
    		synchronized(Resource_052.class){
    			while(true){
    				System.out.println("this is a  synchronized static method——method5.");
    				try {
    					Thread.sleep(2000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			}
    	}
    	
    	synchronized public static void method6(){   //与method5等价
    		while(true){
    			System.out.println("this is a  synchronized static method——method6.");
    			try {
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    }
    
    class Thread1_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread1_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		this.rs.method1();  //调用synchronized方法
    	}
    }
    class Thread0_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread0_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		this.rs.method0();  //调用普通方法
    	}
    }
    class Thread2_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread2_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		this.rs.method2();  //调用另一个synchronized方法
    	}
    }
    class Thread3_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread3_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		this.rs.method3();  //调用synchronized static方法
    	}
    }
    class Thread4_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread4_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		this.rs.method4();  //调用普通static方法
    	}
    }
    class Thread5_052 implements Runnable{
    	private Resource_052 rs;
    	/**
    	 * constructor
    	 * @param rs
    	 */
    	public Thread5_052(Resource_052 rs){
    		this.rs = rs;
    	}
    	@Override
    	public void run(){
    		rs.flag=false;
    		this.rs.method5();  //调用锁Class的方法
    		try {
    			Thread.sleep(2000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

      得到的结果如下:

    ==================================================================================================

    调用synchronized方法的thread1启动后主程序等待2秒,确保在其它线程执行之前thread1获得对象锁
    this is a synchronized method——method1.
    this is a synchronized method——method1.
    主程序等待10秒,等前面的线程除thread1和被阻塞的线程外都执行完成,后面的代码将做锁class测试....
    this is a ordinary method——method0.
    this is a synchronized static method——method3.
    this is a ordinary static method——method4.      //从这里的结果可以看到synchronized 普通方法method3没有执行
    this is a synchronized method——method1.
    this is a synchronized method——method1.
    this is a synchronized method——method1.
    this is a synchronized method——method1.
    10秒等待完。
    主程序等待10秒,确保thread5获得class的对象锁,确保thread1和被阻塞的线程都终止。
    this is a synchronized static method——method5.
    this is the second synchronized method——method2.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    10秒等待完。
    this is a ordinary method——method0.
    this is a ordinary static method——method4.
    this is the second synchronized method——method2.  //可以看到synchronized static方法method3没有执行
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.
    this is a synchronized static method——method5.


    ==================================================================================================

    作者:苍枫露雨
             
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    RAP开发入门-主题更换
    RAP开发入门-开发笔记-bug记录
    RAP开发入门-运行过程简析(三)
    Redis入门笔记-redis内部数据结构(01)
    JAVA基础-子类继承父类实例化对象过程
    RAP开发入门-开发笔记
    RAP开发入门-运行第一个HelloWorld(二)
    android maven eclipse
    字符与编码(摘录)
    Python 学习lesson 1
  • 原文地址:https://www.cnblogs.com/chrischennx/p/3594360.html
Copyright © 2011-2022 走看看