简介:

线程同步
多个线程操作同一个资源。
并发:同一个对象被多个线程同时操作。
形成条件:队列+锁。
处理多线程时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这是我们就需要线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。
由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问的正确性,在访问时加入锁机制Synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可,存在以下问题:

1.一个线程持有锁会导致其他所有需要此锁的线程挂起。
2.在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
3.如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题。

同步方法:
由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是Synchronized关键字,它包括两种用法:Synchronize方法和Synchronize块。
同步方法:public Synchronize void method(int args){}

Synchronize方法控制对“对象”的访问,每个对象对应一把锁,每个Synchronize方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行。
缺陷:若将一个大的方法申明为Synchronize将会影响效率。
方法里面需要修改的内容才需要加锁,锁的太多,浪费资源。

Lock(锁):ReentrantLock(可冲入锁)
1.从jdk5.0开始,java提供了更强大的线程同步机制,通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
2.java.util.concurrent.lock.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
3.ReentrantLock类实现可Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显示加锁,释放锁。

Synchronized 与Lock的对比:
1.Lock是显示的锁(手动开启和关闭锁,别忘记关闭锁) Synchronized是隐式锁,出了作用域自动释放。
2.Lock只有代码块锁,Synchronized有代码块锁和方法锁。
3.使用Lock锁,jvm将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性。
4.优先使用顺序:

Lock>同步代码块(已经进入了方法体,分配了相应资源)>同步方法(在方法体之外)

公平锁和非公平锁:
公平锁:有一个线程持有一把锁,新的线程来的时候,不能抢,去队列排队。(cpu调度也不是先到先得)
非公平锁:无法保证锁的获取是按请求锁的顺序进行的,会导致某些线程永远获取不到锁。(synchroized是非公平锁,ReentrantLock是支持非公平锁和公平锁,默认是非公平锁,但可以设置成公平锁)
ReentrantLock:先通过CAS尝试获取锁,如果此时已有线程占据了锁,那就加入aqs队列并且被挂起。当锁释放后,排在队列首的线程会被唤醒,然后CAS再次尝试获取锁。

乐观锁与悲观锁:
乐观锁:认为自己在使用数据的时候不会有别的线程修改数据。
悲观锁:共享资源只能给一个线程使用,其他线程阻塞,用完以后再把资源转让给其他线程。
Synchronized与ReentrantLock都是独占锁,是悲观锁。虽然ReentrantLock使用的是和CAS一样的compareAndSet相关的方法实现的,但是CAS是乐观锁,ReentrantLock却是悲观锁。因为ReentrantLock使用了setExclusiveOwnerThread方法,这个方法就是将某一个线程设置为独占线程。该线程占用该方法后就无法被其他线程占有,这也就是线程互斥,所以不符合乐观锁的定义。

Volatile:
一个变量定义为Volatile后,它具备两种特性:
1.保证此变量对所有线程的可见性,是指当一条线程修改了这个变量的值,新值对于其他线程是立即可见的;
2.指令重排序。

相关文章
|
1月前
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
41 1
|
3月前
|
SQL 关系型数据库 MySQL
MySQL使用行级锁时,并非直接锁定记录,而是锁定涉及的索引。对于表`user_item`,更新语句先锁定非主键索引`idx_1`,再锁定主键索引。若两条更新语句分别按不同顺序锁定这两个索引,可能导致互相等待对方释放锁,引发死锁。解决方案包括先查询待更新记录的主键,再按主键更新,确保一致的锁定顺序。
43 2
|
3月前
|
SQL 关系型数据库 MySQL
临键锁引发的死锁
【8月更文挑战第4天】
40 0
临键锁引发的死锁
|
Linux API C++
锁、避免死锁等相关
锁、避免死锁等相关
67 0
《锁》有那些?
锁是计算机科学中用于控制对共享资源的访问的一种同步机制。不同种类的锁适用于不同的场景和需求。下面是一些常见的锁的种类及其详细介绍:
72 1
|
存储 算法 安全
辛辛苦苦的劳动成果,如何上把锁?
辛辛苦苦的劳动成果,如何上把锁?
|
数据可视化 Java
lock锁和死锁
lock锁和死锁
共享锁(读锁)和排他锁(写锁)
共享锁(读锁)和排他锁(写锁)
142 0
|
存储 对象存储
|
PHP
并发锁(二):共享锁和独占锁
并发锁(二):共享锁和独占锁
214 0
并发锁(二):共享锁和独占锁