线程同步:Java中多线程并发控制如果多个线程同时对一个共享变量增删改查,那么会发生冲突,所以要加入同步锁来保证一个变量只能被一个线程锁定,从而保证了变量的唯一性和准确性。
- 同步方法
用synchronized关键字修饰方法。当用此关键字修饰方法,内置锁会保护整个方法。
如果用synchronized修饰static方法,那么调用这个方法时会锁住整个类。
2.同步代码块
用synchronized修饰语句块。被修饰的语句块会自动被加上内置锁。
同步代码块比同步方法的细粒度更高,通常不需要锁住整个方法,使用sysnchronized锁住代码块即可。
3.使用volatile
使用volatile关键字来修饰字段(成员变量),就是告诉程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,能保证所有线程对变量访问的可见性。
4.使用reentrantlock
支持重进入的锁,表示锁能够支持一个线程对资源的重复加锁。除此之外,该锁还支持获取锁时的公平和非公平性选择。
一般重入锁大幅降低了程序的运行效率,不推荐使用
5.使用局部变量
ThreadLocal,即线程变量,是以ThreadLocal对象为键、任意对象为值的存储结构。这个结构被附带在线程上,一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上的一个值。set(T)方法可以设置一个值,get()方法可以获取到原先设置的值。
6.使用阻塞队列
LinkedBlockingQueue<T>实现线程同步。
一般线程阻塞有三种情况:
1⃣️等待阻塞:wait(),notify(),notifyAll()
2⃣️同步阻塞:JVM把线程放在锁池中
3⃣️其他阻塞:sleep(),join()。
7.使用原子变量
原子操作:读取变量值,修改变量值,保存变量值是一个整体。
比如AtomicInteger表可以用原子方式更新int的值,可以在应用程序中,但是不能替换掉Integer。
8.管道输入/输出流
管道输入/输出与普通的文件输入/输出或者网络输入/输出流不同之处在于,它主要用于线程之间的数据传输,而传输的媒介为内存。
管道的输入/输出主要包括了4种具体实现:PipedOutputStream、PipedInputStream、PipedReader