synchronized关键字的作用范围

本文探讨了Java中synchronized关键字的常见误解,通过实例演示了当多个线程操作不同实例时synchronized锁为何不起作用,并给出了正确的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Synchronized的误解

昨日终于对synchronized这个关键字有了更进一步的理解,记录一下,方便日后查询。

假设我有一个这样的类:

class MultiThreadTest implements Runnable {

	int myId;
	
	public MultiThreadTest(int id) {
		myId = id;
	}

	@Override
	public synchronized void run() {
		for (int i = 0; i < 3; i++) {
			System.out.println("myId is " + i + " : " + Thread.currentThread().getName());
		}
	}
}

main函数如下:

public static void main(String[] args) {
	 new Thread(new MultiThreadTest(1)).start();
	 new Thread(new MultiThreadTest(2)).start();
	 new Thread(new MultiThreadTest(3)).start();
}

在main函数中,我使用三个thread调用它,因为synchronized关键字的关系,最后的理想结果应该是

myId is 0 : Thread-1
myId is 1 : Thread-1
myId is 2 : Thread-1
myId is 0 : Thread-0
myId is 1 : Thread-0
myId is 2 : Thread-0
myId is 0 : Thread-2
myId is 1 : Thread-2
myId is 2 : Thread-2

即所有的thread应该是锁定直至自身运行结束为止,才运行下一个

但是实际结果却是这个样子

myId is 0 : Thread-2
myId is 0 : Thread-0
myId is 0 : Thread-1
myId is 1 : Thread-2
myId is 1 : Thread-0
myId is 2 : Thread-0
myId is 2 : Thread-2
myId is 1 : Thread-1
myId is 2 : Thread-1

很显然,各个线程之间的运行还是乱的,synchronized并没有起到任何作用。

为什么会这样?

原因在于main调用thread是,实际上是new了 3 个 instances,这样一来,java就将之视为3个独立的程序(大概是这个意思,但是用词不准确)

我们现在来看看java对于synchronized的相关描述

synchronized has two effects:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the stat e of the object are visible to all threads.

注意,这里面的关键字是the same object,也就是说,synchronized的作用只针对同一个object或者说instance有效。而上面的main中,却一下子new了3个instance,对于java来说,相当于3个不同的object,而这三个objects分别只运行了一次,所以synchronized在这里面就毫无意义了,就算将run()函数前的synchronized去掉,结果也没有区别。

如何得到理想结果呢?

其实上面已经告诉我们答案了,就是the same object,无论你有多少个thread,只要调用的都是同一个instance,那么这个synchronized就会起作用。

如果main函数改成这样

public static void main(String[] args) {

	Runnable r = new MultiThreadTest();

	new Thread(r).start();
	new Thread(r).start();
	new Thread(r).start();
}

就能得到理想结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值