2.2.16鎖對(duì)象的改變

在將任何數(shù)據(jù)類型作為同步鎖時(shí),需要注意的是,是否有多個(gè)線程同時(shí)持有鎖對(duì)象,如果同時(shí)持有相同的鎖對(duì)象,則這些線程之間就是同步的;如果分別獲得鎖對(duì)象,這些線程之間就是異步的。

/**
 * @author wuyoushan
 * @date 2017/4/19.
 */
public class MyService {
    private String lock="123";

    public void testMethod(){
        try {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " begin " +
                        System.currentTimeMillis());
                lock = "456";
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + " end " +
                        System.currentTimeMillis());
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}

/**
 * @author wuyoushan
 * @date 2017/4/4.
 */
public class ThreadA extends Thread{

    private MyService service;

    public ThreadA(MyService service) {
        this.service = service;
    }

    @Override
    public void run() {
       super.run();
        service.testMethod();
    }
}

/**
 * @author wuyoushan
 * @date 2017/4/4.
 */
public class ThreadB extends Thread{

   private MyService service;

    public ThreadB(MyService service) {
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.testMethod();
    }
}

/**
 * @author wuyoushan
 * @date 2017/3/20.
 */
public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyService service=new MyService();
        ThreadA a=new ThreadA(service);
        a.setName("A");
        ThreadB b=new ThreadB(service);
        b.setName("B");
        a.start();
        Thread.sleep(50);
        b.start();
    }
}

程序運(yùn)行后的結(jié)果為:

A begin 1493684592096
B begin 1493684592146
A end 1493684594096
B end 1493684594146

程序的結(jié)果是異步輸出的。因?yàn)?0毫秒過后B取得的鎖是“456”

/**
 * @author wuyoushan
 * @date 2017/3/20.
 */
public class Run {
    public static void main(String[] args) throws InterruptedException {
        MyService service=new MyService();
        ThreadA a=new ThreadA(service);
        a.setName("A");
        ThreadB b=new ThreadB(service);
        b.setName("B");
        a.start();
//        Thread.sleep(50);
        b.start();
    }
}

去掉Thread.sleep(50),程序的運(yùn)行結(jié)果如下:

A begin 1493685002103
A end 1493685004104
B begin 1493685004104
B end 1493685006104

線程A和B持有的鎖都是“123”,雖然將鎖改成了“456”,但是結(jié)果還是同步的,因?yàn)锳和B共同爭搶的鎖是“123”。

還需要提示一下,只要對(duì)象不變,即使對(duì)象的屬性被改變,運(yùn)行的結(jié)果還是同步。

/**
 * @author wuyoushan
 * @date 2017/4/10.
 */
public class Service {
   public void serviceMethodA(UserInfo userInfo){
        synchronized (userInfo){
            try {
                System.out.println(Thread.currentThread().getName());
                userInfo.setUserName("abcabcabc");
                Thread.sleep(3000);
                System.out.println("end! time="+System.currentTimeMillis());
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
   }
}

/**
 * @author wuyoushan
 * @date 2017/4/4.
 */
public class ThreadA extends Thread{

    private Service service;
    private UserInfo userInfo;

    public ThreadA(Service service,UserInfo userInfo) {
        super();
        this.service = service;
        this.userInfo=userInfo;
    }

    @Override
    public void run() {
       super.run();
       service.serviceMethodA(userInfo);
    }
}

/**
 * @author wuyoushan
 * @date 2017/4/4.
 */
public class ThreadB extends Thread{

    private Service service;
    private UserInfo userInfo;

    public ThreadB(Service service,UserInfo userInfo) {
        this.service = service;
        this.userInfo=userInfo;
    }

    @Override
    public void run() {
        super.run();
        service.serviceMethodA(userInfo);
    }
}

/**
 * @author wuyoushan
 * @date 2017/3/20.
 */
public class Run {
    public static void main(String[] args){
        try {
            Service service = new Service();
            UserInfo userInfo = new UserInfo();
            ThreadA a = new ThreadA(service, userInfo);
            a.setName("a");
            a.start();
            Thread.sleep(50);

            ThreadB b = new ThreadB(service, userInfo);
            b.setName("b");
            b.start();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}

程序的運(yùn)行結(jié)果為:

a
end! time=1493685934399
b
end! time=1493685937399

摘選自 java多線程核心編程技術(shù)-2.2.16

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,918評(píng)論 0 11
  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請(qǐng)注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 2,306評(píng)論 0 14
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,606評(píng)論 1 15
  • metamacro_concat這個(gè)宏也很簡單,連接而已:
    大劉閱讀 788評(píng)論 0 0
  • 研三即將畢業(yè)的你,收到了兩份 offer :一來自實(shí)習(xí)過的科技公司,公司同事優(yōu)秀,老板不錯(cuò),培訓(xùn)制度完善;二是來自...
    陳素封閱讀 768評(píng)論 1 16

友情鏈接更多精彩內(nèi)容