synchronized 方法与锁对象

来源:互联网 发布:tensorflow vgg 编辑:程序博客网 时间:2024/05/17 08:33

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

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= AmethodA endbegin methodA threadName= BmethodA 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= Abegin methodB threadName= BmethodA endmethodB 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= AmethodA endbegin methodB threadName= BmethodB 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
原创粉丝点击