2.2.16锁对象的改变

Posted 成功的路上总是离不开贵人的帮助,名师的指点和小人的刺激。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.2.16锁对象的改变相关的知识,希望对你有一定的参考价值。

在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的,如果分别获得锁对象,这些线程之间是异步的。

package com.cky.thread;

/**
 * Created by edison on 2017/12/9.
 */
public class MyServIce {
    private String lock ="123";
    public void testMethodA (){
        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();
        }
    }
}
package com.cky.thread;

/**
 * Created by edison on 2017/12/8.
 */
public class ThreadA extends  Thread{
    private MyServIce service;

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

    @Override
    public void run() {
        super.run();
        service.testMethodA();
    }
}
package com.cky.thread;

/**
 * Created by edison on 2017/12/8.
 */
public class ThreadB extends  Thread{


    private MyServIce service;

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

    @Override
    public void run() {
        super.run();
        service.testMethodA();
    }
}
package com.cky.thread;

/**
 * Created by edison on 2017/12/9.
 */
public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        MyServIce myServIce = new MyServIce();
        ThreadA a = new ThreadA(myServIce);
        a.setName("A");
        ThreadB b= new ThreadB(myServIce);
        b.setName("B");
        a.start();
        Thread.sleep(50);
        b.start();


    }
}

结果分析:

因为50毫秒过后线程B 获得的锁是456

继续测试:

去掉代码Thread.sleep(50)

package com.cky.thread;

/**
 * Created by edison on 2017/12/9.
 */
public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        MyServIce myServIce = new MyServIce();
        ThreadA a = new ThreadA(myServIce);
        a.setName("A");
        ThreadB b= new ThreadB(myServIce);
        b.setName("B");
        a.start();
        //Thread.sleep(50);
        b.start();


    }
}
Bbegin=1512803944419
Bend=1512803946419
Abegin=1512803946419
Aend=1512803948419

  

线程A和B持有的锁都是123,虽然将锁改成了456。但是结果还是同步的,因为线程A和B共同争抢的锁是123

注意:只要对象不变,即使对象的属性被改变,运行的结果还是同步的,测试如下

 

package com.cky.daemon;

/**
 * Created by edison on 2017/12/9.
 */
public class Service {
    public void methodA(UserInfo userInfo) {
        synchronized (userInfo) {
            try {
                System.out.println("begin"+Thread.currentThread().getName());
                userInfo.setUsrname("aaaa");
                Thread.sleep(2000);
                System.out.println("end"+ System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
package com.cky.daemon;

/**
 * Created by edison on 2017/12/9.
 */
public class UserInfo {
    private String usrname;

    public String getUsrname() {
        return usrname;
    }

    public void setUsrname(String usrname) {
        this.usrname = usrname;
    }
}
package com.cky.daemon;

import com.cky.thread.ThreadA;
import com.cky.thread.ThreadB;

/**
 * Created by edison on 2017/12/9.
 */
public class Test {
    public static void main(String[] args) {
        try {
            Service service = new Service();
            UserInfo userInfo = new UserInfo();
            ThreadA threadA = new ThreadA(service, userInfo);
            threadA.setName("a");
            threadA.start();
            Thread.sleep(50);
            ThreadB threadB = new ThreadB(service, userInfo);
            threadB.setName("b");
            threadB.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.cky.thread;

import com.cky.daemon.Service;
import com.cky.daemon.UserInfo;

/**
 * Created by edison on 2017/12/8.
 */
public class ThreadA extends  Thread{
    private Service service;
    private UserInfo userInfo;

    public ThreadA(Service service, UserInfo userInfo) {

        this.service = service;
        this.userInfo = userInfo;
    }

    @Override
    public void run() {
        super.run();
        service.methodA(userInfo);
    }
}
package com.cky.thread;

import com.cky.daemon.Service;
import com.cky.daemon.UserInfo;

/**
 * Created by edison on 2017/12/8.
 */
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.methodA(userInfo);
    }
}
begina
end1512804642120
beginb
end1512804644121

 

以上是关于2.2.16锁对象的改变的主要内容,如果未能解决你的问题,请参考以下文章

Thread--对象锁猜想

并发技术12线程锁技术的使用

java并发线程锁技术的使用

ReentrantReadWriteLock场景应用

互斥锁 & 共享锁

静态方法内的同步块将获取类级别锁或对象级别锁