Java多线程--synchronized(一)

synchronized关键字

脏读问题

package ch02.test1;
/*
   脏读
 */
public class PublicVar {
    private String name = "a";
    private String pwd = "aa";

    public void setValue(String name, String pwd) {

        try {
            this.name = name;
            Thread.sleep(5000);

            this.pwd = pwd;
            System.out.println("setValue method thread name = " + Thread.currentThread().getName()
                    + "name=" + this.name + " pwd=" + this.pwd);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void getValue() {
        System.out.println("getValue method thread name=" + Thread.currentThread().getName()
            +"name=" + this.name + " pwd=" + this.pwd);
    }
}

class MyThread extends Thread {
    private PublicVar publicVar;

    public MyThread(PublicVar publicVar) {
        this.publicVar = publicVar;
    }

    @Override
    public void run() {
        super.run();
        this.publicVar.setValue("b","bb");
    }
}

class Test {
    public static void main(String[] args) {
        try {
            PublicVar publicVar = new PublicVar();
            MyThread myThread = new MyThread(publicVar);
            myThread.start();
            Thread.sleep(200);

            publicVar.getValue();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

output:

getValue method thread name=mainname=b pwd=aa
setValue method thread name = Thread-0name=b pwd=bb
  • 脏读的原因
    getValue()方法不同步

  • 脏读的解决
    用synchronized关键字修饰getValue()方法

  • 当线程A调用anyObject对象的synchronized方法X时,A线程就获得了对象锁。此时:

  1. 其他线程必须等待A线程执行完X方法才能执行X方法,以及anyObject对象的其他synchronized方法
  2. 其他线程调用anyObject对象的非synchronized方法不受影响

synchronized锁重入

  • 什么是锁重入
    使用synchronized时,当一个线程得到一个对象锁后,它再次请求对象锁是可以获得对象锁的。
    简而言之,就是自己可以再次获得自己的内部锁
  • 如果没有锁重入,会导致死锁
package ch02.test2;
/*
    可重入锁
 */
public class Service {
    public synchronized void service1() {
        service2();
        System.out.println("service1");
    }
    public synchronized void service2() {
        service3();
        System.out.println("service2");
    }
    public synchronized void service3() {
        System.out.println("service3");
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        new Service().service1();
    }
}
 class Test {
     public static void main(String[] args) {
         MyThread myThread = new MyThread();
         myThread.start();
     }
 }

output:

service3
service2
service1

一些结论

  • 当存在继承关系时,子类可以通过“可重入锁”调用父类的同步方法。
  • 出现异常,锁自动释放
  • 同步不可以继承
posted @ 2020-09-10 22:07  来一块小饼干  阅读(89)  评论(0编辑  收藏  举报