java线程 - synchronized详解

synchronized : 代表同步的修饰符

目录

1.特性:

2.互斥性demo:

3.重入性讲解


1.特性:

  1. 互斥性(排他性) : 同一时刻,只允许一个线程进行访问,会一直等待线程释放锁,容易造成死锁。
  2. 重入性: 程序或者子程序可以在任意时刻被中断然后系统调度另一段代码,这段代码又调用了该子程序,并不会出错。 也                 就是说,一个线程执行了某个程序,是可以再次进入该程序并执行。

        内置锁:类借用synchronized是实现了一个内置性,我觉得更像是类的特性,只不过是类借用了这个修饰符来实现的内置                          性。所有类都可以用自身对象创建一个内置锁。

2.互斥性demo:

一 . synchronized修饰普通方法:针对的是对象的某一实例。(并不影响对象的其他实例)


package com.test.concurrencyThread;

public class Test implements Runnable {

    public synchronized void test() {
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

    public static void main(String[] args) {
        Runnable runnable = new Test();
        Runnable runnable1 = new Test();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread thread1 = new Thread(runnable1);
        thread1.start();
    }
}



程序输出:

Thread-0
Thread-1
(两者几乎同时输出)


package com.test.concurrencyThread;

public class Test implements Runnable {

    public synchronized void test() {
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

    public static void main(String[] args) {
        Runnable runnable = new Test();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread thread1 = new Thread(runnable);
        thread1.start();
    }
}



再看这第二个demo,由两个线程启动同一个Test的实例,输出的结果没变,只是在输出thread-0之后过了5秒,才输出Thread-1。

Thread-0
Thread-1

由此可见,synchronized修饰普通方法:针对的是对象的某一实例。(并不影响对象的其他实例)。


二. synchronized修饰静态方法:针对的是整个类。

package com.test.concurrencyThread;

public class Test implements Runnable {

    public synchronized static void test1() {
        try {
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

    public static void main(String[] args) {
        Runnable runnable = new Test();
        Runnable runnable1 = new Test();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread thread1 = new Thread(runnable1);
        thread1.start();
    }
}



 接下来synchronized修饰静态方法,无论是创建一个实例还是两个实例,都是先输出一个,之后过了5秒,再输出第二个。

Thread-0
Thread-1

由此可见,synchronized修饰静态方法:针对的是整个类


三. synchronized修饰代码块:针对的是synchronized修饰的对象,(不影响synchronized修饰的其他对象)


package com.test.concurrencyThread;

public class Test implements Runnable {

    private final Object object = new Object();

    private void test1() {
        synchronized (object) {
            try {
                System.out.println(Thread.currentThread().getName());
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

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

    public static void main(String[] args) {
        Runnable runnable = new Test();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread thread1 = new Thread(runnable);
        thread1.start();
    }
}



创建一个Test实例,由两个线程运行。结果也是先输出一个,过五秒之后,又输出第二个。

Thread-0
Thread-1


package com.test.concurrencyThread;

public class Test implements Runnable {

    private final Object object = new Object();

    private void test1() {
        synchronized (object) {
            try {
                System.out.println(Thread.currentThread().getName());
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

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

    public static void main(String[] args) {
        Runnable runnable = new Test();
        Runnable runnable1 = new Test();
        Thread thread = new Thread(runnable);
        thread.start();
        Thread thread1 = new Thread(runnable1);
        thread1.start();
    }
}



Thread-0
Thread-1
结果几乎同时输出。由此可见,synchronized修饰代码块:针对的是synchronized修饰的对象,(不影响其他synchronized修饰的对象)。


3.重入性讲解

当一个线程请求一个由其他线程持有的对象锁时,该线程会阻塞。当线程请求自己持有的对象锁时,如果该线程是重入锁,请求就会成功,否则阻塞。

我们回来看synchronized,synchronized拥有强制原子性的内部锁机制,是一个可重入锁。因此,在一个线程使用synchronized方法时调用该对象另一个synchronized方法,即一个线程得到一个对象锁后再次请求该对象锁,是永远可以拿到锁的

在Java内部,同一个线程调用自己类中其他synchronized方法/块时不会阻碍该线程的执行,同一个线程对同一个对象锁是可重入的,同一个线程可以获取同一把锁多次,也就是可以多次重入。原因是Java中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。   

------此段引用 https://www.cnblogs.com/cielosun/p/6684775.html

猜你喜欢

转载自blog.csdn.net/qq_34561892/article/details/83999707