Java高并发

高并发主要组件:synchronizer / 同步容器 / ThreadPool、executor

volatile

volatile,一个可以使变量在多个线程中是可见的,当一个volatile修饰的值改变了,则会通知其他线程修改为最新的值,从而使多个线程之间一个变量的保持可见行,是一种无锁同步,但是只有可见性,没有原子性

synchronized锁

synchronized是如果是同一个锁对象,则是可以重入的锁,如:

  1. 同一个类的不同方法,可以持有同一把锁
  2. 父类的锁和子类的锁可以为持有同一把锁

因为锁定的为同一个对象子类的synchronized可以调用父类的synchronized方法,所以持有相同的锁

在线程中如果异常出现,则会自动释放锁,导致线程余下程序不是线程安全,需要慎重处理异常

synchronized可以保持原子性和可见性

作为锁的对象,属性可以变化,如果锁的对象发生变化,则也会变化,锁的是new的栈的对象,而不是引用,所以new新的对象,则会影响前一个对象的变化

不以字符串常量来作为锁的对象

原理主要是:JMM,包含主内存,线程内存之间的数据同步和原子的问题

对象锁为当前对象的锁,仅限于当前锁的方法和对象,无锁不受影响,但是可能存在脏读,应该枷锁保持一致性,多个锁的方法为同一把锁,则无需额外获取锁,当前锁即可调用

多线程之wait/notify:

  1. 先锁定对象,必须在synchronized
  2. 不满足条件就进入等待,并释放锁,等待锁的notify的方法,则执行
  3. 如果满足其他线程的条件,则调用notify唤醒其他线程,在调用自己的wait释放锁给其他线程先执行

不建议使用wait/notify

实现一个容器,一个线程插入一定的内容,另一个线程监控到一定数量时发出警报

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// wait/notify
public class Mycontainer{
List data = new ArrayList();

public void set(Object o){
data.add(o);
}

public void size(){
return data.size();
}

public static void main(String[] args){
Mycontainer c =new Mycontainer();

final Object lock =new Object();

new Thread(() -> {
synchronized (lock) {
if( c.size != 5) {
//1. 条件不满足,通知t1运行,并释放锁
lock.wait();
}
//4. t2运行完,自动释放锁,通知t1继续
lock.notify();
}
}),"t2").start();

new Thread(() -> {
synchronized (lock) {
for(int i =0; i< 10; i++) {
if(c.size() == 5) {
//2. 通知t2可以运行了
lock.notify();
try{
//3. 并释放锁给t2运行
lock.wait();
}catch(Exception e) {

}
}
}
}
}),"t1").start();
}
}
// CountDownLatch
public class Mycontainer1{
List data = new ArrayList();

public void set(Object o){
data.add(o);
}

public void size(){
return data.size();
}

public static void main(String[] args){
CountDownLatch latch = new CountDownLatch(1);

new Thread(() -> {
if(c.size() != 5) {
try{
latch.await();//不用锁定对象,一直等待,等着改变开门
}catch(Exception e) {

}
}
}),"t2").start();

new Thread(() -> {
for(int i =0; i< 10; i++) {
c.set(new Object());

if(c.size() ==5) {
latch.countDown();//打开门,执行t2
}
}
}),"t1").start();
}
}

原子类型

简单的数字运算,采用Atomic*的类型

lock

必须手动释放锁,为可重入锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ReentrantLock1{
Lock lock = new ReentrantLock();

void m1(){
try{
lock.lock();
}finally{
lock.unlock();
}
}

void m2(){
boolean locked = lock.tryLock();
if(locked) lock.unlock();

boolean locked = false;
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);

}finally{
lock.unlock();
}
}
}
-------------本文结束感谢您的阅读-------------
Dean Wang wechat