Synchronized

简介: JUC学习

Synchronized 关键

synchronized 是 Java 中的关键字,是一种同步锁。它修饰的对象有以下几种:

1.修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}

括起来的代码,作用的对象是调用这个代码块的对象;

2.修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

虽然可以使用 synchronized 来定义方法,但synchronized 并不属于方法定义

的一部分,因此,synchronized 关键字不能被继承。如果在父类中的某个方法

使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这个方

法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上synchronized 关键字才可以。当然,还可以在子类方法中调用父类中相应的方

法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。

3.修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

4.修饰一个类,其作用的范围是 synchronized 后面括号括起来的部分,作用主

的对象是这个类的所有对象。


对象锁:包括方法锁(默认锁对象为this,当前实例对象)和同步代码块锁(自己指定锁对象)

著作权归https://pdai.tech所有。
链接:https://pdai.tech/md/java/thread/java-thread-x-key-synchronized.html
public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence = new SynchronizedObjectLock();
    @Override
    public void run() {
        // 同步代码块形式——锁为this,两个线程使用的锁是一样的,线程1必须要等到线程0释放了该锁后,才能执行
        synchronized (this) {
            System.out.println("我是线程"+ Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +"结束");
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
    }
}

输出结果:

我是线程Thread-0
Thread-0结束
我是线程Thread-1
Thread-1结束
public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence = new SynchronizedObjectLock();
    // 创建2把锁
    Object block1 = new Object();
    Object block2 = new Object();
    @Override
    public void run() {
        // 这个代码块使用的是第一把锁,当他释放后,后面的代码块由于使用的是第二把锁,因此可以马上执行
        synchronized (block1) {
            System.out.println("block1锁,我是线程"+ Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("block1锁,"+Thread.currentThread().getName() +"结束");
        }
        synchronized (block2) {
            System.out.println("block2锁,我是线程"+ Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("block2锁,"+Thread.currentThread().getName() +"结束");
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
    }
}

结果:

block1锁,我是线程Thread-0
block1锁,Thread-0结束
block2锁,我是线程Thread-0  // 可以看到当第一个线程在执行完第一段同步代码块之后,第二个同步代码块可以马上得到执行,因为他们使用的锁不是同一把
block1锁,我是线程Thread-1
block2锁,Thread-0结束
block1锁,Thread-1结束
block2锁,我是线程Thread-1
block2锁,Thread-1结束

方法锁形式:synchronized修饰普通方法,锁对象默认为this

著作权归https://pdai.tech所有。
链接:https://pdai.tech/md/java/thread/java-thread-x-key-synchronized.html
public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence = new SynchronizedObjectLock();
    @Override
    public void run() {
        method();
    }
    public synchronized void method() {
        System.out.println("我是线程"+ Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +"结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instence);
        Thread t2 = new Thread(instence);
        t1.start();
        t2.start();
    }
}

输出结果:

我是线程Thread-0
Thread-0结束
我是线程Thread-1
Thread-1结束

类锁:指synchronize修饰静态的方法或指定锁对象为Class对象

synchronize修饰静态方法

public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence1 = new SynchronizedObjectLock();
    static SynchronizedObjectLock instence2 = new SynchronizedObjectLock();
    @Override
    public void run() {
        method();
    }
    // synchronized用在普通方法上,默认的锁就是this,当前实例
    public synchronized void method() {
        System.out.println("我是线程"+ Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +"结束");
    }
    public static void main(String[] args) {
        // t1和t2对应的this是两个不同的实例,所以代码不会串行
        Thread t1 = new Thread(instence1);
        Thread t2 = new Thread(instence2);
        t1.start();
        t2.start();
    }
}

输出结果

我是线程Thread-0
我是线程Thread-1
Thread-1结束
Thread-0结束

实例2:

public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence1 = new SynchronizedObjectLock();
    static SynchronizedObjectLock instence2 = new SynchronizedObjectLock();
    @Override
    public void run() {
        method();
    }
    // synchronized用在静态方法上,默认的锁就是当前所在的Class类,所以无论是哪个线程访问它,需要的锁都只有一把
    public static synchronized void method() {
        System.out.println("我是线程"+ Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +"结束");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instence1);
        Thread t2 = new Thread(instence2);
        t1.start();
        t2.start();
    }
}

输出结果:

我是线程Thread-0
Thread-0结束
我是线程Thread-1
Thread-1结束

synchronized指定锁对象为Class对象

public class SynchronizedObjectLock implements Runnable {
    static SynchronizedObjectLock instence1 = new SynchronizedObjectLock();
    static SynchronizedObjectLock instence2 = new SynchronizedObjectLock();
    @Override
    public void run() {
        // 所有线程需要的锁都是同一把
        synchronized(SynchronizedObjectLock.class){
            System.out.println("我是线程"+ Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +"结束");
        }
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(instence1);
        Thread t2 = new Thread(instence2);
        t1.start();
        t2.start();
    }
}

输出结果:

我是线程Thread-0
Thread-0结束
我是线程Thread-1
Thread-1结束


目录
相关文章
|
2月前
|
算法 Java 编译器
Synchronized你又知道多少?
Synchronized 是 JVM 实现的一种互斥同步机制,通过 monitorenter 和 monitorexit 指令控制对象锁的获取与释放。锁的本质是对象头的标记,确保同一时间只有一个线程访问资源。Synchronized 支持可重入性,允许方法内部调用其他同步方法而不阻塞。JVM 对锁进行了优化,引入了自旋锁、偏向锁、轻量级锁和重量级锁,以减少系统开销。Synchronized 属于悲观锁,而乐观锁基于 CAS(Compare and Swap)算法实现非阻塞同步,提高并发性能。
64 6
|
6月前
|
Java
synchronized
synchronized
31 2
|
6月前
|
存储 安全 Java
ReentrantLock和Synchronized简单比较
ReentrantLock和Synchronized简单比较
46 0
|
Java
07.synchronized都问啥?
大家好,我是王有志。经过JMM和锁的铺垫,今天我们正式进入synchronized的内容,来看看关于synchronized面试中都会问啥?
65 1
07.synchronized都问啥?
Synchronized
作用:能够保证在同一时刻最多有一个线程执行该段代码,以保证并发的安全性。(当第一个线程去执行该段代码的时候就拿到锁,并独占这把锁,当方法执行结束或者一定条件后它才释放这把锁,在没释放锁之前,所有的线程处于等待状态)
72 0
synchronized的总结
synchronized的总结
synchronized的总结
|
前端开发 Java Spring
方法上加上 synchronized 就可以了么
方法上加上 synchronized 就可以了么
|
存储 缓存 安全
synchronized的简单理解
synchronized的简单理解
99 0