【线程】Java 中是如何实现线程同步的?

Java 中是如何实现线程同步的?

  • 使用synchronized 关键字实现的同步代码块、同步方法(悲观锁)

  • 使用特殊域变量(volatile)实现线程同步(保证 可见性、有序性。比如说使用volatile实现 线程安全的双检查锁单例模式)

  • ThreadLocal(每个线程获取的都是该变量的副本)

  • 使用 可重入锁 实现线程同步(相对 synchronized 锁粒度更细了,效率更高)

    • 在java.util.concurrent 包,即常说的JUC,提供了很多并发安全类,可以支持同步。

    • 如:ReentrantLock 类是可重入、可中断、可设置超时时间、可设置公平锁、可支持多个条件变量的锁,是 Lock 接口实现类

      • ReentrantLock() : 创建一个 ReentrantLock 实例

      • ReentrantLock 实例.lock() : 获得锁

      • ReentrantLock 实例.unlock() : 释放锁

  • java.util.concurrent.atomic 包 (乐观锁)

    • 方便程序员在多线程环境下,无锁的进行原子操作,原理是CAS(可以从这里引入到CAS上面)
  • 使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,

    副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。变量局部化。

阻塞线程的方式有哪些?

当发生如下情况时,线程将会进入阻塞状态:

  • 线程调用sleep()方法主动放弃所占用的处理器资源;
  • 线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;
  • 线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有;
  • 线程在等待某个通知(notify);
  • 程序调用了线程的suspend()方法将该线程挂起,但这个方法容易导致死锁,所以应该尽量避免使用该方法。

终止线程的方式有哪些?

stop 方法终止线程(线程不安全,不推荐)

直接使用thread.stop()来强行终止线程,线程会立即终止执行,可能会产生不可预料的结果。在调用thread.stop()后会导致该线程所持有的所有锁突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用 stop 方法来终止线程。

使用退出标志退出线程

public volatile boolean exit = false;
public void run() {
    while (!exit){
      //do something
    }
}

通过使用volatile修饰的boolean类型的共享变量,在设置exit等于true时,该运行中的线程会退出while循环,执行完run方法结束

Interrupt方法结束线程

使用interrupt()方法来中断线程有两种情况:

  • 线程处于阻塞状态:如使用了sleep,wait,await,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常,通过代码捕获该异常,然后break跳出循环状态,结束这个线程的执行。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的,一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。
public void run () {
    //非阻塞过程中通过判断中断标志来退出
    while (!Thread.interrupted()) {
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            //捕获到异常之后,执行 break 跳出循环
            break;
        }
    }
}
  • 线程处于非阻塞状态:使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。

Thread.currentThread().isInterrupted()和Thread.interrupted()的区别?

两者都是判断当前线程是否中断,isInterrupted()不会清除中断标志,interrupted()会清除掉中断标志。

你可能感兴趣的:(线程,java,开发语言)