• 多线程 synchronized关键字锁对象和方法区别


      首先提出问题:

      1 当一个类中有多个synchronized方法的时候,多线程访问不同的方法会不会阻塞?

      2 synchronized(this)和synchronized(非this 对象x)的区别是什么?

      下面我们实验:

      为图省事,将两个问题放在一起验证。

      定义7个方法,分别在主线程中调用,

      

    public class MyMethod {
    
    	synchronized public void methodA() {
    		try {
    			System.out.println(Thread.currentThread().getName()+"  into methodA  " +System.currentTimeMillis());
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	synchronized public void methodB() {
    		try {
    			System.out.println(Thread.currentThread().getName()+"  into methodB  "  +System.currentTimeMillis());
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	synchronized public void methodC(){
    		try {
    			System.out.println(Thread.currentThread().getName()+"  into methodC  "  +System.currentTimeMillis());
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	synchronized public void methodD(){
    		try {
    			System.out.println(Thread.currentThread().getName()+"  into methodD  "  +System.currentTimeMillis());
    			Thread.sleep(1000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	public void methodE(){
    		try {
    			synchronized (this) {
    				System.out.println(Thread.currentThread().getName()+"  into methodE  "  +System.currentTimeMillis()+"  **");
    				Thread.sleep(1000);
    			}
    		} catch (Exception e) {
    		}
    	}
    	public void methodF(String lock){
    		try {
    			synchronized (lock) {
    				System.out.println(Thread.currentThread().getName()+"  into methodF  "  +System.currentTimeMillis()+"  **");
    				Thread.sleep(1000);
    			}
    		} catch (Exception e) {
    		}
    	}
    	
    	public void methodJ(String lock){
    		try {
    			synchronized (lock) {
    				System.out.println(Thread.currentThread().getName()+"  into methodJ  "  +System.currentTimeMillis()+"  **");
    				Thread.sleep(1000);
    			}
    		} catch (Exception e) {
    		}
    	}
    }
    

     main方法

    public class Run {
    
    	public static void main(String[] args) {
    		
    		MyMethod method=new MyMethod();
    		String lock="";
    		//开启四个线程,分别调用四个方法
    		for (int i = 0; i < 7; i++) {
    			final int temp=i;
    			Thread thread=new Thread(new Runnable() {
    				@Override
    				public void run() {
    					switch (temp) {
    					case 0:method.methodA();break;
    					case 1:method.methodB();break;
    					case 2:method.methodC();break;
    					case 3:method.methodD();break;
    					case 4:method.methodE();break;
    					case 5:method.methodF(lock);break;
    					case 6:method.methodJ(lock);break;
    					}
    				}
    			});
    			thread.start();
    		}
    		
    		
    
    	}
    
    }
    

      为了省事,本人一起写在for循环中,本人测试的顺序是。

      注调其他case,调用A ,B,C,D四个方法

    控制台

    Thread-0  into methodA  1533211474985
    Thread-3  into methodD  1533211475986
    Thread-2  into methodC  1533211476986
    Thread-1  into methodB  1533211477987
    

      可以发现,同一个类中多个synchronized同步方法是阻塞的。

      解开第五个,调用A,B,C,D,E五个方法

    控制台

    Thread-0  into methodA  1533211570137
    Thread-4  into methodE  1533211571137  **
    Thread-3  into methodD  1533211572138
    Thread-2  into methodC  1533211573139
    Thread-1  into methodB  1533211574139
    

      看时间戳会发现,方法E和其他方法阻塞,所以,synchronized同步方法锁是当前对象。

      在解开第六个,调用A,B,C,D,E,F六个方法

    控制台

    Thread-1  into methodB  1533211712907
    Thread-5  into methodF  1533211712907  **
    Thread-4  into methodE  1533211713908  **
    Thread-3  into methodD  1533211714909
    Thread-2  into methodC  1533211715910
    Thread-0  into methodA  1533211716910
    

      可以发现,F和B的时间是一模一样的,所以,他们之间是异步的,因为锁的对象不同。而另外的方法和代码块锁的都是当前对象,所以互斥。

      解开第七个,七个方法全部调用。

    控制台

    Thread-0  into methodA  1533211922515
    Thread-5  into methodF  1533211922516  **
    Thread-4  into methodE  1533211923516  **
    Thread-6  into methodJ  1533211923516  **
    Thread-3  into methodD  1533211924517
    Thread-2  into methodC  1533211925518
    Thread-1  into methodB  1533211926519
    

      可以发现,F和J是阻塞的。因为锁的是同一个对象。

    总结:synchronized 锁方法锁的是当前对象,synchronized(this)锁的也是当前对象。所以同一个类中,当有多个synchronized方法的时候,他们是互相阻塞的,同时也会阻塞synchronized(this)代码块中的内容。

          synchronized(this)时锁当前对象,此时一个类中的多个synchronized方法,或者锁当前对象的会互相阻塞。而锁非this对象的时候,和此时异步的,并不会阻塞。而锁非this对象的时候,当非this对象是同一个对象的时候,也会呈现同步效果。

       synchronized(非this对象x)格式的写法,是将x对象当做"对象监视器",这样就有下面三个结论:

      1)当多个线程访问synchronized(非this对象x){}代码块的时候,呈现同步效果。

      2)当其他线程执行x对象中的synchronized(this){}代码块的时候,呈现同步效果。

      3)当其他线程执行x对象中的synchronized同步方法的时候,呈现同步效果。

      每个优秀的人,都有一段沉默的时光。不抱怨,不诉苦,最后度过那段感动自己的日子。

  • 相关阅读:
    Python对象
    python 迭代器和生成器
    python中logging日志模块详解
    学习中遇到的一些问题(杂谈)
    如何在github上搜索项目
    python闭包与装饰器
    python面试题
    selenium
    python导入自定义包
    About Me、
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/9409578.html
Copyright © 2020-2023  润新知