并行工作者模型
多线程中的问题,主要是由于
- 任务顺序
- 共享资源
造成的。
竞态条件
当多个线程访问同一资源时,如果对资源的访问顺序敏感,则称存在竞态条件。
导致竞态条件发生的代码区称做临界区。
例:
-
count++;
-
先检测后执行
对于main线程,如果文件a不存在,则创建文件a,但是在判断文件a不存在之后,Task线程创建了文件a,这时候先前的判断结果已经失效,(main线程的执行依赖了一个错误的判断结果)此时文件a已经存在了,但是main线程还是会继续创建文件a,导致Task线程创建的文件a被覆盖、文件中的内容丢失等等问题。
死锁
M个线程、N个资源,相互等待对方资源。
避免:注意嵌套的同步块,不要试图在不同的对象上获取锁。
public class A {
private String source1;
private String source2;
public A(String source1, String source2) {
this.source1 = source1;
this.source2 = source2;
}
public void doSomething() {
synchronized (source1) {
System.out.println("A synchronized source1 ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (source2) {
System.out.println("A synchronized source2 ...");
System.out.println("A do something.");
}
}
}
}
public class B {
private String source1;
private String source2;
public B(String source1, String source2) {
this.source1 = source1;
this.source2 = source2;
}
public void doSomething() {
synchronized (source2) {
System.out.println("B synchronized source2 ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (source1) {
System.out.println("B synchronized source1 ...");
System.out.println("B do something.");
}
}
}
}
public class Client {
public static void main(String[] args) {
String source1 = "source1";
String source2 = "source2";
A a = new A(source1, source2);
B b = new B(source1, source2);
new Thread(() -> a.doSomething()).start();
new Thread(() -> b.doSomething()).start();
}
}
活锁
运行着,重复着无用功
尝试 - 失败 - 尝试 … 可能成功
饥饿
- 高优先级线程一直占着资源,低优先级线程饥饿
- 1个线程一直占着资源,其他线程饥饿