守护线程:
守护线程终止自身无法终止,不传递IO、File等
作用:
-
为其他线程提供支持服务
-
任何情况
线程状态:
java.lang.Thread.State
枚举提供6种
线程安全:全局变量及静态变量引起
线程同步:
最常见加锁:每次只允许一个加锁
java三个同步:
-
同步代码块:
作用:把访问共享数据的代码锁起来
synchronized
作用某个区块,只对这个区块的资源实行互斥访问
实例用this,静态用对象
CountDownLatch类
:同步辅助工具,每个线程结束,cutDown()数量减一,wait()等计数器中数字清空
2.同步方法:
synchronized
修饰方法
锁对象:实例锁this,静态锁对象时类的字节码对象(.class)
同步代码与同步方法的区别:
-
粒度不同:
-
同步代码块:在同步代码块中,你可以选择精确控制哪部分代码需要同步,只有被包裹在同步块内的代码会受到同步锁的保护。
-
同步方法:同步方法会将整个方法体都加上同步锁,这意味着只要线程进入这个方法,它就会获得锁,而不仅仅是某个特定的代码块。
-
-
锁的对象不同:
-
同步代码块:你可以显式指定要用作同步锁的对象,通常是一个共享资源的引用或一个专门创建的锁对象。
-
同步方法:同步方法默认使用的锁是当前对象(即
this
),或者如果是静态方法,则是类的Class对象。
-
-
可读性和维护性:
-
同步方法通常更简单,因为不需要显式地创建锁对象或在代码块中指定锁对象。这可以提高代码的可读性和维护性。
-
同步代码块可以提供更细粒度的控制,但可能需要更多的代码来创建和管理锁。
-
-
性能:
-
同步方法可能会导致性能问题,因为它会锁住整个方法,而其他线程可能需要等待直到方法执行完毕。
-
同步代码块可以在一定程度上提高性能,因为只有部分代码受到同步锁的保护,其他线程可以在不受影响的情况下执行其他代码块。
-
3.Lock锁:接口
JDK5:ReetrantLock
,当线程获取该锁再次获取不会阻塞
Volatile关键字:不能保证原子性
修饰共享变量(实例、静态)
特点:可见性和禁止指令重排序优化
-
可见性(Visibility):当一个变量被声明为
volatile
时,它保证了所有线程对该变量的读取操作都能看到最新的值。这意味着当一个线程修改了volatile
变量的值时,该值会立即被写入主内存,其他线程读取这个变量时会从主内存中获取最新值,而不是从线程的本地缓存中获取。 -
禁止指令重排序(Prevent Reordering):
volatile
关键字还具有禁止编译器和处理器对被标记的变量进行指令重排序的作用。这确保了在变量的读取和写入操作之间不会发生意外的重排序,从而保证了多线程环境下的正确性。
应用场景:
-
变量的写操作不依赖于变量的当前值,或者只有一个线程对变量进行写操作,而多个线程只对变量进行读操作的情况。
-
变量在多线程之间不需要复杂的操作,如加锁和解锁。
如果需要更复杂的线程同步和互斥操作,通常会使用synchronized
关键字或java.util.concurrent
包中提供的更高级的同步工具,如Lock
接口、Semaphore
、CountDownLatch
等。
线程通信:
多个线程共享资源,避免无效的资源争抢
wait():挂起当前线程,并释放共享资源的锁
notify():调用任意对象的notify()方法会在因调用该对象的wait()方法而阻塞的线程中随机选择一个线程解除阻塞,但要等到获得锁后才可以真正执行
notifyAll():调用任意对象的notifyAll()方法会在因调用该对象的wait()方法而阻塞的所有线程一次性全部解除阻塞。
wait()、notify()、notifyAll()都是Object中的final方法,被所有的类继承并不能重写,wait()、notify()与同步代码、同步方法一起出现(synchronized),否则会抛出异常。