Java 多线程之synchronized(一)

package com.company.thread.synchronize;

/**
 * @Description TODO
 * @Author zhouxinjian
 * @Date 2019-07-19 09:49
 **/

public class PublicVar {
    public String username = "A";
    public String password = "AA";

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

    }

    public static void main(String[] args) throws InterruptedException {
        PublicVar var = new PublicVar();
        Thread thread = new Thread(){
            @Override
            public void run() {
                var.setValue("B", "BB");
            }
        };
        thread.start();

        Thread.sleep(200);
        var.getValue();
    }
}

当A线程调用anyObject对象加入synchronized 关键字的X方法时,A线程就获得X方法锁,也即对象锁,所以其他线程必须等A线程执行完毕才可以调用X方法,但B线程可以调用其他非synchronized同步方法。

当A线程调用anyObject对象加入synchronized 关键字的X方法时,A线程就获得X方法锁,也即对象锁,所以其他线程必须等A线程执行完毕才可以调用X方法,如果B线程如果调用声明了synchronized的非X方法时,必须等A线程将X方法执行完,也就是释放了对象锁后才可以学调用。

2、synchronized 锁重入

     在使用synchronized时,当一个线程得到一个对象锁后,再次请求对象锁时是可以得到该对象的锁的。即在synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远得到锁的。

      "可重入锁“的概念是:自己可以再次获得自己的内部锁。如有一个线程获得某个对象的锁,此时这个对象锁还没释放,当其再次想获取这个对象锁的时候还是可以获取的,如果不可锁重入,就会造成死锁。

       当存在子父类继承关系时,子类完全可以通过“可重入锁”调用父类同步方法。

       多个线程调用同一个对象的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果是按顺序执行,同步阻塞的。

        这说明synchronized方法或synchronized(this)同步代码块分别有两种作用:

      synchronized同步

(1)对其他synchronized 同步方法或synchronized(this)同步代码块调用呈阻塞作用

(2)同一时间只有一个线程可以执行synchronized同步方法中的代码。

  (3)   synchronized(非this对象)同步,对象监视器必须是同一个,否则就是异步调用。

/**
 * @Description TODO
 * @Author zhouxinjian
 * @Date 2019-07-19 10:15
 **/

public class Service {
    public synchronized void service1() {
        System.out.println("service1");
        service2();
    }

    public synchronized void service2() {
        System.out.println("service2");
        service3();
    }

    public synchronized void service3() {
        System.out.println("service3");
    }

    public static void main(String[] args) {
        Service service = new Service();
        Runnable runnable = () -> {
            service.service1();
        };
        new Thread(runnable).start();
    }
}

synchronized还可以用在static静态方法上,如果这样就是对当前的*.java 对应的class类进行持锁。Class锁可以对类的所有对象实例起作用。

public class Service1 {
    public synchronized static void printA() {
        try {
            System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"进入printA");
            Thread.sleep(3000);
            System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"离开printA");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized static void printB() {
        try {
            System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"进入printB");
            Thread.sleep(3000);
            System.out.println("线程 "+Thread.currentThread().getName()+" "+System.currentTimeMillis()+"离开printB");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Service1 s1 = new Service1();
        Service1 s2 = new Service1();

        new Thread(()->{
            s1.printA();
        },"A").start();

        new Thread(()->{
            s2.printB();
        },"B").start();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_36996888/article/details/96474949