synchronized 是 Java 语言中内置的关键字,用于实现线程同步,以确保多线程环境下共享资源的安全访问。
原子性:synchronized 关键字保证了同一时间只有一个线程能访问同步代码块或同步方法,从而实现了原子性操作。 可见性:synchronized 关键字确保所有线程在访问共享资源时,看到的是最新的值,避免了缓存一致性问题。 有序性:synchronized 关键字可以防止指令重排序,使得同步代码块或同步方法内的指令执行顺序与源代码顺序一致。 可重入:synchronized 关键字支持可重入性,即一个线程可以多次获得同一个锁,而不会导致死锁。 |
对象锁:synchronized 关键字使用对象锁来实现同步。每个对象都有一个内置的锁(monitor)和一个与之关联的等待队列。
锁获取:当一个线程进入同步代码块或同步方法时,将尝试获取与锁对象关联的 monitor。如果 monitor 未被其他线程占用,该线程将获得锁并执行同步代码;如果 monitor 被其他线程占用,该线程将进入等待队列并等待锁。
锁释放:当线程执行完同步代码块或同步方法后,它将释放锁并唤醒等待队列中的一个线程(如果存在)。
synchronized为同步的意思,这个同步这个词在计算机中是存在多种意思的,不同的上下文中,会有不同的含义.
比如,在多线程中,线程安全中,同步其实指的是"互斥".
比如,在IO或者网络编程中,同步相对的词叫做"异步",此处的同步和互斥没有任何关系,和线程也没有关系了,表示的是消息的发送方,如何获取到结果.
1.直接修饰普通的方法
给方法直接加上 synchronized 关键字,此时进入方法就会自动加锁,离开方法,就会自动解锁.如果直接修饰普通方法,也就相当于把锁对象指定为 this 了.
当一个线程加锁成功的时候,其他线程尝试加锁,就会触发阻塞等待(此时对应的线程 就处在 BLOCKED 状态),阻塞会一直持续到占用锁的线程把锁释放为止.
使用 synchronized 的时候,本质上是在针对某个"对象"进行加锁,此时锁对象就是 this,在 Java 中,每个类都是继承自 Object ,每个 new 出来的实例,里面一方面包含了设置好的属性,一方面包含了“对象头”,对象的一些元数据
需要显式指定针对哪个对象加锁.(Java 中的任意对象都可以作为锁对象)
这种随手拿个对象都能作为所对象的用法,这是 Java 中非常有特色的设定(别的语言都不是这么搞.正常的语言都是有专门的锁对象)
this代表当前对象的引用,Counter类只创建了一个counter,调用方法时两个都是counter,都调用increase方法,会有两个线程都对this加锁,就会产生锁的竞争,代码执行从无序到有序.
当两个线程同时针对一个对象加锁,才会产生竞争,如果两个线程针对不同对象加锁,就不会有竞争
相当于针对当前类的类对象加锁
Counter.class