多线程—synchronized

synchronized俗称对象锁,它采用互斥的方式让同一时刻至多只有一个线程持有对象锁,其他线程想获取这个对象锁时就会阻塞,这样就不用担心上下文切换。

关系:synchronized使用对象锁保证了临界区(下面有介绍)内代码的原子性(完整性),临界区内的代码对外是不可分割的,不会被线程上下文切换所打断

注意:同一个临界区,线程访问的对象锁应该是一致的,就好比进入同一个房间,钥匙必须都是那一把,才能达到锁住的目的。

Java中互斥和同步都可以采用synchronized来完成,但有区别:

(1)互斥是保证临界区的竞态条件(下面有介绍)发生,同一时刻只能有一个线程执行临界区代码。

(2)同步是由于线程执行的先后顺序不同,需要一个线程等待其他线程运行到某个点(比如获取结果等)。

语法:保证想要执行临界区的线程都要获取括号里面的对象的对象锁。

synchronized(对象)
{
	临界区
}

加在方法上:

//加在方法上,也是锁的对象,锁的是当前方法的对象(this),对整个方法起作用
public synchronized void test(){
	
}

加在静态方法上:

//加在静态方法上,锁的类对象,而不是this对象,对整个方法起作用
public synchronized static void test(){
	
}

场景理解:

A线程获取到synchronized代码块的对象锁后,同时cpu给A线程分配时间片,此时A线程就可以进入到synchronized代码块执行,其它线程要执行synchronized代码块,发现对象锁已经被占用,因此进入BLOCKED阻塞状态;如果A线程没有执行完synchronized代码块,那么它不会释放对象锁(除非调用wait),因此,其它线程也无法进入synchronized代码块执行代码,并且cpu也不会给处在BLOCKED阻塞状态的线程分配时间片,因此下一次会再分配时间片给A线程,直到A线程执行完synchronized代码块,释放对象锁,并且唤醒处在BLOCKED阻塞状态的线程,让其处于RUNNABLE状态,如果此时有多个线程,那么它们将会竞争。

扫描二维码关注公众号,回复: 13355102 查看本文章

临界区:

临界区表示一种公共资源或共享资源,可以被多个线程使用,但是一次只能有一个线程使用。一旦临界区被线程占用,其他线程像使用临界区就必须等待。

竞态条件(两种):

  1. read-modify-write(读-改-写):例如:i++,先读取值,计算,最后写回。

  2. check-then-act(检测而后行动):例如:if条件判。先取值,然后根据值判断下一步干什么。

猜你喜欢

转载自blog.csdn.net/qq_42251944/article/details/120861275