多线程笔记一篇
Posted lebronchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程笔记一篇相关的知识,希望对你有一定的参考价值。
周末不在家,没空写文章,就把笔记整理一下发出来了
线程安全
线程安全主要指运行一段代码,在多线程和单线程情况下运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的;
线程不安全主要指多个线程对同一个对象中的同一个实例进行操作时会出现值被修改、值不同步的情况。
interrupt
interrupt():设置interrput状态
interrupted():检查interrupt状态,会清除interrup状态,静态方法
isInterrupted():检查interrup状态
sleep状态调用interrupt(),interpt状态调用sleep都会抛出InteruptedException,并清除interupt状态
stop
stop方法会抛出java.lang.ThreadDeath错误,不是异常
stop方法会释放锁,可能导致数据不一致
suspend、resume
suspend暂停线程,resume恢复暂停的线程,都废弃了
suspend会独占资源和锁,syso的锁都可能被suspend抢占,导致其他syso被阻塞
suspend会在资源内部暂停,可能会导致数据不一致
yield
yield会放弃当前CPU资源,让给其他任务
yield放弃当前CPU资源,可能会被自己抢占
线程优先级
线程优先级1-10
继承性:子线程和父线程优先级一样
优先级高的不一定先执行完
优先级差距大点才有明显效果
守护线程
没有用户线程了,守护线程就会自动销毁
setDemon(true)可以将线程成守护线程
synchronized
synchronized方法
synchronized方法使用的是对象锁
synchronized可以锁重入,一个线程获得对象锁之后,可以在此获得该对象锁,也就是在一个synchronized方法内部可以调用其他synchronized方法
出现异常,锁自动释放
同步不具有继承性
synchronized同步代码块
synchronized(obj)以制定obj为锁
synchronized(this)和synchronized方法互斥
静态synchronized方法
静态synchronized方法使用类文件作为锁
静态synchronized方法和synchronized(XXX.class)互斥
死锁
锁嵌套容易导致死锁
线程A持有锁X,尝试获取锁Y;线程B持有锁Y,尝试获取锁X,线程A,B都阻塞
volatile
volatile使变量在多个线程间可见
读操作之前执行load,读取主内存,写操作之后执行store命令更新主内存
保证可见性,不保证原子性
为保证原子性,可以使用原子类AtomicInteger,但还是推荐使用synchronzed实现原子性
synchronized和volatile对比
volatile不会阻塞,synchronized会阻塞
volatile保证可见,不保证原子;synchronized保证原子,间接保证可见
volatile为了保证变量在多线程之间的可见性;synchronized为了保证多线程访问资源的同步性
读操作之前执行load,读取主内存,写操作之后执行store命令更新主内存;synchronized获取锁之前清空工作内存,从主内存中拷贝变量到工作内存,执行结束后刷新工作内存中的变量到主内存,然后释放锁
wait notify
wait、notify都是Object类的方法
wait、notify方法需要需要获得对象级别的锁,否则会抛出IllegalMonitorStateException异常
wait方法会释放锁
notify方法不会释放锁
执行notify方法的线程执行完之后才会释放锁
wait方法会将该线程放到该锁对象的“预执行队列”中
notify方法释放对象锁后,对象的“预执行队列”中的线程会竞争对象锁,获取到对象锁的线程会被唤醒
被唤醒的线程执行完毕之后会释放对象锁,但是对象的“预执行队列”中的线程不会再被唤醒,除非再次调用notify方法
notifyAll方法可以唤醒对象锁的“预执行队列”中的所有线程
nitify方法执行后,对象的“预执行队列”竞争对象锁的时候可能是优先级高的线程优先执行,可能是随机执行,取决于JVM的实现
线程wait时执行interpt方法会抛出InterptedException异常
wait(long)如果在指定时间内没被唤醒,可以自己唤醒自己,但还是需要竞争锁
join
线程A调用线程B,线程B调用join方法会让线程A被阻塞,直到线程B执行结束再执行
join(long)会指定主线程的等待时间
join方法的原理是wait,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。
join方法会释放锁
Lock
Lock、ReentrantLock、Contition等都是JDK1.5新出来的API
Lock具有嗅探锁定、多路分支通知的功能,比synchronized更加灵活
Condition的await、signal、aignalAll和Object的wait、notify、notifyAll对应
wait、notify、notifyAll需要获得对象锁;await、signal、aignalAll需要被Lock锁定
使用Lock+Condition实现生产者消费者比使用Synchronized+wait的好处在于Condition可以实现多路分支通知,生产者唤醒消费者,消费者唤醒生产者
公平锁、非公平锁
公平锁FIFO,非公平锁随机获得sianal顺序
new ReentrantLock()默认非公平锁
new ReentrantLock(boolean fair)可选择公平锁,非公平锁
ReentrantReadWriteLock 读写锁
ReentrantLock可以理解为排他锁,锁定所有方法
ReentrantReadWriteLock可以实现读锁和写锁
读读共享,读写互斥,写写互斥
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.writeLock().lock();
生产者消费者模型
Synchronized+wait
package com.lebron.design;
import java.util.ArrayList;
import java.util.List;
public class ProCustomTest {
public static void main(String[] args) {
Store store = new Store();
Producter producter = new Producter(store);
Customer customer = new Customer(store);
for (int i=0; i<10; i++) {
new Thread(producter, "Productor-" + i).start();
new Thread(customer, "Customer-" + i).start();
}
try {
Thread.sleep(200000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Producter extends Thread {
private Store store;
public Producter (Store store) {
this.store = store;
}
public void run() {
while (true) {
store.add(String.valueOf(System.currentTimeMillis()));
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
class Customer extends Thread {
private Store store;
public Customer (Store store) {
this.store = store;
}
@Override
public void run() {
while (true) {
store.remove();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Store {
private static final int MAX_SIZE = 10;
private List<String> goodsList = new ArrayList<String>();
public synchronized void add (String goods) {
while (goodsList.size() == MAX_SIZE) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
goodsList.add(goods);
System.out.println(Thread.currentThread().getName() + " add goods:" + goods + " size:" + goodsList.size());
this.notifyAll();
}
public synchronized void remove() {
while (goodsList.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String remove = goodsList.remove(0);
System.out.println(Thread.currentThread().getName() + " remove goods:" + remove + " size:" + goodsList.size());
this.notifyAll();
}
}
Lock+Condition(替换Store类)
class Store {
private static final int MAX_SIZE = 10;
private List<String> goodsList = new ArrayList<String>();
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
public void add (String goods) {
lock.lock();
while (goodsList.size() == MAX_SIZE) {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
goodsList.add(goods);
System.out.println(Thread.currentThread().getName() + " add goods:" + goods + " size:" + goodsList.size());
condition2.signalAll();
lock.unlock();
}
public void remove() {
lock.lock();
while (goodsList.size() == 0) {
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String remove = goodsList.remove(0);
System.out.println(Thread.currentThread().getName() + " remove goods:" + remove + " size:" + goodsList.size());
condition1.signalAll();
lock.unlock();
}
}
线程交替打印模型
synchronized + wait
public class OrderTest {
public static void main(String[] args) {
OrderClass orderClass = new OrderClass();
new PrintA(orderClass).start();
new PrintB(orderClass).start();
new PrintC(orderClass).start();
}
}
class PrintA extends Thread {
private OrderClass orderClass;
public PrintA (OrderClass orderClass) {
this.orderClass = orderClass;
}
@Override
public void run() {
while (true) {
orderClass.pringA();
}
}
}
class PrintB extends Thread {
private OrderClass orderClass;
public PrintB (OrderClass orderClass) {
this.orderClass = orderClass;
}
@Override
public void run() {
while (true) {
orderClass.pringB();
}
}
}
class PrintC extends Thread {
private OrderClass orderClass;
public PrintC (OrderClass orderClass) {
this.orderClass = orderClass;
}
@Override
public void run() {
while (true) {
orderClass.pringC();
}
}
}
class OrderClass {
private volatile int orderIndex = 0;
public synchronized void pringA() {
while (orderIndex % 3 != 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
orderIndex ++;
this.notifyAll();
}
public synchronized void pringB() {
while (orderIndex % 3 != 1) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
orderIndex ++;
this.notifyAll();
}
public synchronized void pringC() {
while (orderIndex % 3 != 2) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
orderIndex ++;
this.notifyAll();
}
}
Lock + Condition(替换OrderClass)
class OrderClass {
private volatile int orderIndex = 0;
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void pringA() {
lock.lock();
while (orderIndex % 3 != 0) {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
orderIndex ++;
condition2.signal();
lock.unlock();
}
public void pringB() {
lock.lock();
while (orderIndex % 3 != 1) {
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
orderIndex ++;
condition3.signal();
lock.unlock();
}
public void pringC() {
lock.lock();
while (orderIndex % 3 != 2) {
try {
condition3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
orderIndex ++;
condition1.signal();
lock.unlock();
}
}
扫码关注,不迷路
以上是关于多线程笔记一篇的主要内容,如果未能解决你的问题,请参考以下文章