synchronized使用总结

java多线程同步处理经常会使用到synchronized关键字,之前对其使用场景有些模糊不清,故做一些整理。

一、使用synchronized修饰非静态方法

1 public class Hello{
2 
3    public synchronized void sayHello(){
4     System.out.println("Hello world");
5   }
6 }

这种方式是对每一个Hello对象上锁,第一个访问该方法的线程A则持有当前Hello对象的锁,线程B要访问该对象的线程会被阻塞,直到线程A访问结束释放该对象的锁线程B才能访问。但是如果线程B访问的是Hello的另外一个对象,则不会被阻塞,因为sayHello是一个非静态方法。

二、使用synchronized修饰静态方法

1 public class Hello{
2 
3    public synchronized static void sayHello(){
4     System.out.println("Hello world");
5   }
6 }

static关键字修饰的方法表示该方法是一个类方法,与类的对象无关,所以当线程A首先持有了sayHello的锁后,线程B无论访问Hello的那个对象都会阻塞。

 

三、使用synchronized同步块

前面两种方法虽然能实现同步,但是效率不是很高。假设Hello有两个被synchronized修饰的方法。当线程A访问sayHello()时会持有Hello对象的锁,这时,如果线程B

去访问sayBye()时会被阻塞,因为访问syaBye()需要持有Hello对象的锁。有时候可能sayHello()和syaBye()并发不会有影响,这样做就会降低程序效率。

public class Hello {

    public synchronized void sayHello() {
        System.out.println("Hello world");
    }
    
    public synchronized void sayBye() {
        System.out.println("bye bye");
    }
}

所以java有了synchronized同步块的使用,同步块也可以分为两种。静态和非静态。

非静态同步块:

public class Hello {

    private final Object lockHello = new Object();
    private final Object lockBye = new Object();
    public void sayHello(){
        synchronized (lockHello) {
            System.out.println("hello");
        }
    }
    public synchronized void sayBye() {
        synchronized (lockBye) {
            System.out.println("bye");
        }
 }
}

  这样当线程A访问sayHello时就不会影响线程B访问sayBye了。静态和非静态的区别与前面两种是一样的。

静态同步块:

public class Hello {

    private static final Object lock = new Object();
    public void sayHello(){
        synchronized (lock) {
            System.out.println("hello");
        }
    }
}

 

posted @ 2016-01-22 23:51  乘风破浪sxg  阅读(652)  评论(0编辑  收藏  举报