java 同步块(Java Synchronized Blocks)

java 同步块(Java Synchronized Blocks)

Java 同步块包括方法同步和代码块同步。java 同步可以避免资源竞争,避免死锁。

主题包括的主要内容:

The Java synchronized Keyword

在java中,同步是用 synchronized 关键字代表的. 同步是针对对象和类来说的。一个对象上的所有同步块只能被一个线程锁住。其他所有的线程试图访问同步块的方法,都要等到占用资源的线程释放了才能访问。

synchronized关键字可以用到4个种场景:

  1. Instance methods
  2. Static methods
  3. Code blocks inside instance methods
  4. Code blocks inside static methods

Synchronized Instance Methods

Here is a synchronized instance method:

  public synchronized void add(int value){
      this.count += value;
  }

当一个方法上用到synchronized关键字,Java才能知道它是个同步方法。

一个实例同步方法只属于实例本身。每个实例都有自己的同步方法。

Synchronized Static Methods

Static methods are marked as synchronized just like instance methods using thesynchronized keyword. Here is a Java synchronized static method example:

  public static synchronized void add(int value){
      count += value;
  }

同样 synchronized 告诉Java 这是一个同步方法。

同步静态方法属于类对象。在VM中只有一个类对象,因此只能有一个线程执行静态同步方法。

Synchronized Blocks in Instance Methods

有时候, 不需要同步整个方法,只需要同步方法里面的一部分,可以借助同步块来完成工作。

Here is a synchronized block of Java code inside an unsynchronized Java method:

  public void add(int value){

    synchronized(this){
       this.count += value;   
    }
  }

这个例子是用同步块标记一块同步代码。这个同步块代码就相当于同步方法。

Notice how the Java synchronized block construct takes an object in parentheses. In the example "this" is used, which is the instance the add method is called on. The object taken in the parentheses by the synchronized construct is called a monitor object. The code is said to be synchronized on the monitor object. A synchronized instance method uses the object it belongs to as monitor object.

对于同一个对象只能有一个线程访问同步块。

下面两个方法的代码,效果是一样的。

 
  public class MyClass {
  
    public synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public void log2(String msg1, String msg2){
       synchronized(this){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
  }

只能有一个线程执行(针对同一个对象) ;

第二个方法是不同的线程执行的时候会在同步块里面发生等待(针对同一对象)。

Synchronized Blocks in Static Methods

下面两个静态方法是在类对象上的:

  public class MyClass {

    public static synchronized void log1(String msg1, String msg2){
       log.writeln(msg1);
       log.writeln(msg2);
    }

  
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);  
       }
    }
  }

一个线程只能在同一时间执行上面的任何一个方法。

对于第二个方法:只能有一个线程在代码块里面执行。

Java Synchronized Example


  public class MyClass {


    public static synchronized void log1(String msg1, String msg2){
	 try {
	    	    TimeUnit.SECONDS.sleep(5) ;
	    	} catch (InterruptedException e) {
	    	    e.printStackTrace();
	    	}
       System.out.println(msg1);
       System.out.println(msg2);
    }
    
    public static synchronized void log3(String msg1, String msg2){
	    System.out.println(msg1);
	    System.out.println(msg2);  
    }
  
    public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
	   try {
	    	    TimeUnit.SECONDS.sleep(3) ;
	    	} catch (InterruptedException e) {
	    	    e.printStackTrace();
	    	}
	   System.out.println(msg1);
	   System.out.println(msg2);  
       }
    }
    
    public static void log4(String msg1, String msg2){
	synchronized(MyClass.class){
	    
	    System.out.println(msg1);
	    System.out.println(msg2);  
	}
    }
    
   
    public void log5(String msg1, String msg2){
	synchronized(this){
	    System.out.println(msg1);
	    System.out.println(msg2);  
	}
    }
    
  }
  public class SynchronizedTest {


    Thread t1 = new Thread(new Runnable() {
        
        @Override
        public void run() {
          
            MyClass.log1("msg11", "msg12") ;
        }
    }) ;
    Thread t2 = new Thread(new Runnable() {
        
        @Override
        public void run() {
           
            MyClass.log2("msg21", "msg22") ;
        }
    }) ;
    Thread t3 = new Thread(new Runnable() {
	
	@Override
	public void run() {
	    
	    MyClass.log3("msg31", "msg32") ;
	}
    }) ;
    
    Thread t4 = new Thread(new Runnable() {
	
	@Override
	public void run() {
	    
	    MyClass.log4("msg41", "msg42") ;
	}
    }) ;
    
    Thread t5 = new Thread(new Runnable() {
	
	@Override
	public void run() {
	    
	   new  MyClass().log5("msg51", "msg52") ;
	}
    }) ;
    
    public static void main(String[] args) {
	SynchronizedTest st = new SynchronizedTest() ;
	
	st.t1.start() ;
//	st.t3.start() ;
	
//	st.t2.start() ;
//	st.t4.start() ;
	st.t5.start() ;
	
	
	 int i = 0 ;
		while(true){
		    try {
			TimeUnit.SECONDS.sleep(1) ;
			System.out.println("---------------> " + i);
			i ++ ;
			
		    } catch (InterruptedException e) {
			e.printStackTrace();
		    }
		    if(i > 10 ){
			    break ;
		    }
		}
		
	
	
    }
    
}

测试组合:

1. 测试实例方法组合;

2. 测试静态方法组合;

3. 测试实例方法和静态方法组合;(注意方法里面的 sleep, 是为了做到更好的测试效果)。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值