• synchronized关键字


    public class ThreadSafe
    {
    
    	public static void main(String[] args)
    	{
    		Safe safe = new Safe();
    		new Thread(new Runnable()
    		{
    
    			public void run()
    			{
    				try
    				{
    					while (true)
    					{
    						safe.setI(100);
    						
    					}
    				}
    				catch (InterruptedException e)
    				{
    					e.printStackTrace();
    				}
    			}
    		}).start();
    		new Thread(new Runnable()
    		{
    
    			public void run()
    			{
    				while (true)
    				{
    					try
    					{
    						safe.getI();
    						
    					}
    					catch (InterruptedException e)
    					{
    						e.printStackTrace();
    					}
    				}
    			}
    		}).start();
    	}
    }
    
    class Safe
    {
    	int i;
    	public Safe()
    	{
    		this.i = 0;
    	}
    
    	public synchronized void setI(int i) throws InterruptedException
    	{
    		System.out.println("setId"+" "+i);
    		Thread.sleep(1000 * 3);
    		System.out.println("backsetId"+" "+100);
    		this.i = i;
    	}
    
    	public synchronized int getI() throws InterruptedException
    	{
    		System.out.println("getId"+" "+i);
    		this.i=10;
    		Thread.sleep(1000 * 3);
    		System.out.println("backgetId"+" "+10);
    		return this.i;
    	}
    }
    

      输出:

    setId 100
    backsetId 100
    getId 100
    backgetId 10
    setId 100
    backsetId 100
    setId 100

    synchronized在方法声明中,锁的是this,

    在jvm汇编指令里面并没有显式的出现monitorenter

    下面代码

    public class ThreadSafe
    {
    
    	public static void main(String[] args)
    	{
    		Safe safe = new Safe();
    		new Thread(new Runnable()
    		{
    
    			public void run()
    			{
    				try
    				{
    					while (true)
    					{
    						safe.setI(100);
    
    					}
    				}
    				catch (InterruptedException e)
    				{
    					e.printStackTrace();
    				}
    			}
    		}).start();
    		new Thread(new Runnable()
    		{
    
    			public void run()
    			{
    				while (true)
    				{
    					try
    					{
    						safe.getI();
    
    					}
    					catch (InterruptedException e)
    					{
    						e.printStackTrace();
    					}
    				}
    			}
    		}).start();
    	}
    }
    
    class Safe
    {
    	int i;
    
    	public Safe()
    	{
    		this.i = 0;
    	}
    
    	public synchronized void setI(int i) throws InterruptedException
    	{
    		System.out.println("setId" + " " + i);
    		Thread.sleep(1000 * 3);
    		System.out.println("backsetId" + " " + 100);
    		this.i = i;
    	}
    
    	public int getI() throws InterruptedException
    	{
    		synchronized (this)
    		{
    			System.out.println("getId" + " " + i);
    			this.i = 10;
    			Thread.sleep(1000 * 3);
    			System.out.println("backgetId" + " " + 10);
    		}
    		return this.i;
    	}
    }
    

      执行结果一样

     public synchronized void setI(int) throws java.lang.InterruptedException;
       Code:
          0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
          3: new           #4                  // class java/lang/StringBuilder
          6: dup
          7: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
         10: ldc           #6                  // String setId
         12: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
         15: iload_1
         16: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
         19: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
         22: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         25: ldc2_w        #11                 // long 3000l
         28: invokestatic  #13                 // Method java/lang/Thread.sleep:(J)V
         31: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         34: ldc           #14                 // String backsetId 100
         36: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         39: aload_0
         40: iload_1
         41: putfield      #2                  // Field i:I
         44: return
    
     public int getI() throws java.lang.InterruptedException;
       Code:
          0: aload_0
          1: dup
          2: astore_1
          3: monitorenter  进入管程
          4: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
          7: new           #4                  // class java/lang/StringBuilder
         10: dup
         11: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
         14: ldc           #15                 // String getId
         16: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
         19: aload_0
         20: getfield      #2                  // Field i:I
         23: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
         26: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
         29: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         32: aload_0
         33: bipush        10
         35: putfield      #2                  // Field i:I
         38: ldc2_w        #11                 // long 3000l
         41: invokestatic  #13                 // Method java/lang/Thread.sleep:(J)V
         44: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         47: ldc           #16                 // String backgetId 10
         49: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         52: aload_1
         53: monitorexit  退出管程
         54: goto          62
         57: astore_2
         58: aload_1
         59: monitorexit
         60: aload_2
         61: athrow
         62: aload_0
         63: getfield      #2                  // Field i:I
         66: ireturn
       Exception table:
          from    to  target type
              4    54    57   any
             57    60    57   any
    

    注意有个方法出现了进入管程指令,退出管程指令,有个方法没有

    来自java虚拟机规范的解释

    Java 虚拟机可以支持方法级的同步和方法内部一段指令序列的同步,这两种同步结构都是使用管程( Monitor)来支持的。方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作( §2.11.8)之中。
    虚拟机可以从方法常量池中的方法表结构( method_info Structure, §4.6)中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有管程,然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放管程。在方法执行期
    间,执行线程持有了管程,其他任何线程都无法再获得同一个管程。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的管程将在异常抛到同步方法之外时自动释放

    monitor和对象的关系.来自jvm文档

    monitor 即可以实现为与对象一同分配
    和销毁,也可以在某条线程尝试获取对象所有权时动态生成,在没有任何线程
    持有对象所有权时自动释放。
    实际上synchoronized关键字修饰方法的时候就是进入对象的monitor,所以第一个代码会出现in-out一组一组的出现,而不会出现in-in2-out这种组合

  • 相关阅读:
    mysql 主从服务器配置
    Linux命令
    Kali
    Python进阶
    性能测试工具
    sphinx搜索
    页面静态化
    PHP API接口
    线程的生命周期
    多线程的创建
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/6823053.html
Copyright © 2020-2023  润新知