synchronized关键字 - - 三种使用方法

文章详细解释了Java中synchronized的三种使用方式:同步代码块、同步非静态方法和同步静态方法,以及它们在多线程环境下的作用和锁的对象。同步代码块用于锁定特定对象,防止多个线程同时访问;同步非静态方法锁定实例对象,而同步静态方法锁定的是类对象。这些机制保证了线程安全,防止数据不一致。

第一种 synchronized(对象) { 临界区 }

synchronized(对象)
{
 	临界区
}

代码实例

static int counter = 0;
static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
	 Thread t1 = new Thread(() -> {
		 for (int i = 0; i < 5000; i++) {
			 synchronized (lock) {
				counter++;
			 }
		 }
	 }, "t1");
	 Thread t2 = new Thread(() -> {
		 for (int i = 0; i < 5000; i++) {
			 synchronized (lock) {
				counter--;
			 }
		 }
	 }, "t2");
}

线程1 和 线程2 竞争同一个共享变量 lock ,当 线程1 锁住 lock 时,线程2 就不能再对 lock 上锁,线程2 会进入阻塞状态,等 线程1 执行完临界区后,会释放 lock,并唤醒 线程2,此时 线程2 才能对 lock 上锁并执行自己的临界区代码

注意事项

  • 当 线程1 对 lock 上锁后,哪怕 线程1 在执行临界区时cpu时间刚好用完,线程1也不会释放lock,线程2 还是处在阻塞状态,不能对lock上锁

  • synchronized 锁住的是引用类型对象,不能是 int、double 等基本类型对象

  • synchronized 锁住的是所有线程共享的全局变量,不能是线程的私有变量

第二种 加在 非静态方法 上

    @Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

    /**
     * @since      1.5
     */
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
    }

以上是 StringBuffer 的源码片段,我们知道 StringBuffer 是线程安全的,就是因为 StringBuffer 的方法上加了 synchronized 关键字

要调用一个类的非静态方法,必须先创建该类的实例对象

当我们给非静态方法加synchronized的时候(此时称为对象锁

当 线程1 要调用这个方法的时候,需要先对实例对象上锁,才是执行方法内的代码

所以,哪怕其他线程想调用该实例对象的其他加了synchronized的非静态方法也会被阻塞(因为 调用该实例对象的其他加了synchronized的非静态方法 需要先对该实例对象上锁,但此时该实例对象已经被 线程1 锁住了

注意:

若此时其他线程调用的是同一个类的另外一个实例对象的synchronized非静态方法则不会被阻塞,因为此时是要对另外一个实例对象上锁,而另外一个实例对象并没被 线程1 上锁

第三种 加在 静态方法上

我们知道调用 静态方法 是无需创建实例对象的,那 我们给静态方法加synchronized的时候,锁住的是什么呢?

答案是 类对象 (比如:Person.class)

此时我们称之为 类锁

当 线程1 调用了 Person 类中 加了 synchronized 的静态方法,就对 Person.class 上锁,当有其他线程要调用Person类的其他加了synchronized 的静态方法 也会被阻塞,因为需要对 Person.class 上锁,但此时 Person.class 已经被 线程1 上锁了

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值