synchronized 方法与锁对象

两个线程均调用共享对象的同步方法:

class MyObject{
    public synchronized void methodA(){
        System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            System.out.println("methodA end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ThreadA extends Thread{
    private MyObject object;

    public ThreadA(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodA();
    }
}

class ThreadB extends Thread{
    private MyObject object;

    public ThreadB(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodA();
    }
}
public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();
        ThreadA a = new ThreadA(object);
        a.setName("A");
        ThreadB b = new ThreadB(object);
        b.setName("B");
        a.start();
        b.start();
    }
}

结果肯定是顺序执行:

begin methodA threadName= A
methodA end
begin methodA threadName= B
methodA end

A线程调用共享对象的同步方法,B线程调用共享对象非同步方法:

class MyObject{
    public synchronized void methodA(){
        System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            System.out.println("methodA end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void methodB(){
        System.out.println("begin methodB threadName= " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            System.out.println("methodB end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ThreadA extends Thread{
    private MyObject object;

    public ThreadA(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodA();
    }
}

class ThreadB extends Thread{
    private MyObject object;

    public ThreadB(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodB();
    }
}
public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();
        ThreadA a = new ThreadA(object);
        a.setName("A");
        ThreadB b = new ThreadB(object);
        b.setName("B");
        a.start();
        b.start();
    }
}

结果是:

begin methodA threadName= A
begin methodB threadName= B
methodA end
methodB end

A线程调用共享对象的同步方法,B线程调用共享对象另一个同步方法

class MyObject{
    public synchronized void methodA(){
        System.out.println("begin methodA threadName= " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            System.out.println("methodA end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void methodB(){
        System.out.println("begin methodB threadName= " + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            System.out.println("methodB end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ThreadA extends Thread{
    private MyObject object;

    public ThreadA(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodA();
    }
}

class ThreadB extends Thread{
    private MyObject object;

    public ThreadB(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.methodB();
    }
}
public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();
        ThreadA a = new ThreadA(object);
        a.setName("A");
        ThreadB b = new ThreadB(object);
        b.setName("B");
        a.start();
        b.start();
    }
}

结果是:

begin methodA threadName= A
methodA end
begin methodB threadName= B
methodB end

结论:
1. A线程和B线程均调用object对象的synchronized方法,则必须是同步方式调用
2. A线程先持有object对象的Lock锁,B线程可以以异步方式调用object对象中的非synchronized类型的方法
3. A线程先持有object对象的Lock锁,B线程如果此时调用object对象中的synchronized类型的方法则需等待,即只能是同步方式调用

结论2即对应了脏读的现象:
比如赋值方法是同步,取值方法是非同步,则可能出现脏读,即在读取实例变量时,此值已经被其他线程更改过了

class MyObject{
    private String username = "A";
    private String password = "AA";

    public synchronized void setValue(String username, String password){
        this.username = username;
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.password = password;
        System.out.println("setValue username : " + username + " password : " + password);
    }

    public void getValue(){
        System.out.println("getValue username : " + username + " password : " + password);
    }
}

class ThreadA extends Thread{
    private MyObject object;

    public ThreadA(MyObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.setValue("B", "BB");
    }
}

public class Run {
    public static void main(String[] args) {
        MyObject object = new MyObject();
        ThreadA a = new ThreadA(object);
        a.setName("A");
        a.start();
        try {
            Thread.sleep(200);//结果受此值影响
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        object.getValue();
    }
}

可对getValue添加synchronzied关键字修饰,避免脏读

当线程调用anyObject对象加入synchronized关键字修饰的X方法时,A线程就获得了X方法锁,更准确的讲是获得了anyObject对象的锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但是其他线程可以调用anyObject的其他非synchronized关键字修饰的方法。可若其他线程调用anyOjbect的其他synchronized关键字修饰的方法时,也必须等待A线程执行完毕,释放了对象锁后才可以调用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值