【多线程】线程互斥之synchronized 详解

定义:
线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
我们都知道保证线程完整执行。则需要对其加锁。使用synchronized关键字。在这里锁的对象理论上可以为任何对象。

代码块同步:

    public void output(String name){

        int len=name.length();
        synchronized(this){
            for (int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println(); 
        }

    }

方法同步:
在方法前直接加关键字synchronized。
public synchronized void output2(String name){
int len=name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}

注意:该方法锁的是this对象,也就是当前类的实例。

静态方法加锁

    public static synchronized void output3(String name){
        int len=name.length();
        for (int i = 0; i < len; i++) {
            System.out.print(name.charAt(i));
        }
        System.out.println(); 
    }

注意:该方法锁的是该方法所在的类本身(并非实例)。

以上有这三种用synchronized 的方式。如果我要同时保证方式一和方式二能够同步。则必须保证,两个方法锁的是用一个对象。也就是方式一要用synchronized (this)。加入这时你换成synchronized (obj)那就没有意义了。
当然也要必须保证两个方法都是在同一个类下调用。如果
Outputer outputer1=new Outputer();
Outputer outputer2=new Outputer();
然后用outputer1,outputer2分别调用两种方式,那也起不到锁的作用了。

即:类的同一个实例下,并锁的是同一个对象。才能达到互斥的效果。

同理,由于方式三是锁的类的本身,所以如果方式一和方式三若想同步的话也要锁住类的本身。假如我们还应用synchronized (this),我做了一个测试。
private void init(){
final Outputer outputer=new Outputer();

new Thread(new Runnable(){
    public void run(){
        while(true){
            try {
                Thread.sleep(10);
            } catch (Exception e) {

            }
            outputer.output3("方法三mdm");
        }
    }
}).start();

new Thread(new Runnable(){
    public void run(){
        while(true){
            try {
                Thread.sleep(10);
            } catch (Exception e) {

            }
            outputer.output("方法一MDM");
        }
    }
}).start();
}
public static void main(String[] args) {
    new TraditionalThreadSynchronized().init();
}

会发现结果出现了异常。该静态方法并没有得到锁的保护。两个方法没有实现同步互斥。

这里写图片描述

因为在静态方法中synchronized 是锁的类本身。因此在方式一种也要锁类的本身。实例化出来的对象是没用的。可以锁住类的字节码对象。即
synchronized (Outputer.class){
//方法体
}

有了上面的介绍,在给大家出个题。

 pulbic class Something(){
         public synchronized void isSyncA(){}
         public synchronized void isSyncB(){}
         public static synchronized void cSyncA(){}
         public static synchronized void cSyncB(){}
     }

那么,加入有Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢

   a.   x.isSyncA()与x.isSyncB() 
   b.   x.isSyncA()与y.isSyncA()
   c.   x.cSyncA()与y.cSyncB()
   d.   x.isSyncA()与Something.cSyncA()

猜你喜欢

转载自blog.csdn.net/u010176014/article/details/52217224