多线程synchronized的使用

2019-01-09  本文已影响0人  IFLEU

  在多线程的使用中,关键字synchronized的使用主要有:1、修饰代码块;2修饰方法。

1、修饰代码块synchronized(obj)

  这里主要有synchronized(this)和synchronized(obj),而()中的即为得到的锁,判断锁是否为同一个即判断是否为同步代码块。它的主要判断是锁对象是否相等,对于值类型而言看值是否相同,对于对象类型则看是否为相同的引用,综合而言即为争夺锁的两个obj是否==。
以下是代码实例:
   1、synchronized(this):this是当前类的对象实例,所以要判断争夺锁的两个obj是否为同一个对象实例,如果为同一个对象实例,则它们之间互斥。

public class SynchronizedTest implements Runnable{

    public void method(){
        try {
            //这里是同步代码块
            synchronized (this){
                System.out.println(Thread.currentThread().getName());
                Thread.sleep(5000);
            }
            System.out.println("5秒已结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        method();
    }

    public static void main(String[] args) {
        //争夺锁的两个对象
        SynchronizedTest synchronizedTest1 = new SynchronizedTest();
        //这里的对象其实是同一个
        //1️⃣SynchronizedTest synchronizedTest2 = synchronizedTest1;
        //两个不同对象
        //2️⃣SynchronizedTest synchronizedTest2 =  new SynchronizedTest();
        Thread thread1 = new Thread(synchronizedTest1);
        Thread thread2 = new Thread(synchronizedTest2);
        thread1.start();
        thread2.start();
    }
}

   1️⃣时得到的为

K%SHK8CXN{JOBY2%Y949F_V.png
   2️⃣时得到的为 KP13Q2L3FZQ3J9}W{UEIM9J.png
  synchronized(this)中的this是类的对象实例,在1️⃣中synchronizedTest1创建了一个对象实例,synchronizedTest2只是去引用了这个对象,即为同一个对象,所以它们是同一个锁,会出现互斥现象;而在2️⃣中synchronizedTest2又重新创建了一个新的对象,和synchronizedTest1不是同一个锁,所以不会出现互斥。
   2、synchronized(obj):正如开始所说,obj如果是值类型则判断值是否相同,对象则同this,总体而言则是判断调用synchronized的obj在内存中的地址是否相同,如果相同,则是争夺同一把锁。synchronized(SynchronizedTest.class),SynchronizedTest.class的地址相同,线程调用同步代码块都会互斥。

2、修饰方法synchronized

  修饰方法主要分为非静态方法和静态方法:
  修饰非静态方法就是看类对象是否是同一个,与synchronized(this)相同。

public class SynchronizedTest implements Runnable {
    public synchronized void method(){
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("5秒已结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        method();
    }

    public static void main(String[] args) {
        //争夺锁的两个对象
        SynchronizedTest synchronizedTest1 = new SynchronizedTest();
         //这里的对象其实是同一个
        //1️⃣SynchronizedTest synchronizedTest2 = synchronizedTest1;
        //两个不同对象
        //2️⃣SynchronizedTest synchronizedTest2 =  new SynchronizedTest();
        Thread thread1 = new Thread(synchronizedTest1);
        Thread thread2 = new Thread(synchronizedTest2);
        thread1.start();
        thread2.start();
    }
}
   1️⃣时得到的为 3K@71FQK{(F3NB2F@3PX3CO.png
   2️⃣时得到的为 1111.png
public class SynchronizedTest implements Runnable {
    public static synchronized void method(){
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("5秒已结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        method();
    }

    public static void main(String[] args) {
        //争夺锁的两个对象
        SynchronizedTest synchronizedTest1 = new SynchronizedTest();
         //这里的对象其实是同一个
        //1️⃣SynchronizedTest synchronizedTest2 = synchronizedTest1;
        //两个不同对象
        //2️⃣SynchronizedTest synchronizedTest2 =  new SynchronizedTest();
        Thread thread1 = new Thread(synchronizedTest1);
        Thread thread2 = new Thread(synchronizedTest2);
        thread1.start();
        thread2.start();
    }
}

  修饰静态方法则与SynchronizedTest.class相同。

  1️⃣2️⃣均会得到 222.png
由此,对于synchronized锁的判断主要是看它们的锁是否是同一个锁,即在内存中的地址是否相同。

修饰非静态方法时,在同一个对象实例中才锁
修饰静态方法时,即同.class
synchronized(obj)根据运行过程中的两个obj是否==来判断是否是同一个锁

上一篇 下一篇

猜你喜欢

热点阅读