Java 锁一 为什么需要锁

75 阅读3分钟

为什么需要锁为什么需要锁

在多线程程序中,多个线程可能会同时访问和修改共享数据。没有适当的同步机制,可能会导致以下问题:

  1. 数据竞争:多个线程同时访问和修改共享数据时,会出现数据不一致的情况。例如,一个线程可能会覆盖另一个线程对共享变量的修改。
  2. 脏读:线程读取到的数据可能是被其他线程部分修改的结果,从而导致数据的不一致性。
  3. 线程安全问题:操作共享数据的线程可能会由于竞态条件而导致程序行为不可预测,进而引发各种错误或异常。

锁的作用

锁的主要作用是确保在同一时刻只有一个线程能够访问共享数据,从而避免上述问题。具体来说,锁的作用包括:

  1. 互斥:通过锁机制,确保同一时刻只有一个线程可以访问共享数据。其他线程在等待锁释放时处于阻塞状态,从而避免了数据竞争。
  2. 同步:锁提供了一种机制,使得线程在对共享数据进行操作时可以正确地协调它们的操作。这包括确保某些操作在其他线程完成之前不会执行。同步:锁提供了一种机制,使得线程在对共享数据进行操作时可以正确地协调它们的操作。这包括确保某些操作在其他线程完成之前不会执行。
  3. 可见性:锁机制确保在一个线程修改共享数据后,其他线程能够看到这些修改。通过内存屏障和同步机制,锁保证了数据的可见性。

锁的类型

  1. 互斥锁(Mutex) :最基本的锁类型,确保同一时刻只有一个线程可以访问资源。
  2. 读写锁(Read-Write Lock) :允许多个线程同时读取共享数据,但在写操作时则排斥所有读操作和其他写操作。
  3. 自旋锁(Spin Lock) :线程在尝试获取锁时不断轮询而不是进入休眠状态,这在锁持有时间较短时可以减少上下文切换的开销。
  4. 重入锁(Reentrant Lock) :允许同一线程多次获得同一个锁,不会导致死锁。
  5. 公平锁与非公平锁:公平锁保证线程请求锁的顺序,而非公平锁允许线程在竞争中插队,从而可能提升性能。

锁的基本实现思路(伪代码)

我们假设一个场景,只有一个坑位的厕所。现在有五个人需要上厕所。是不是每个人都去拉开厕所的门看看里面有没有人

锁的实现方式实际上就是把数据存放到某个变量里面。通过去读取变量的值判断当前是否有其他线程在进行操作

int flag = 0; //0- 厕所没人 1- 厕所有人
if(flag=0){
// 厕所里面没人,我可以上厕所
}else if (flag=1){
    //厕所里面有人,我得等他上完了才能上
}