多线程会导致的问题
- 一共有几类线程安全问题
- 哪些场景需要额外注意县城问题
- 上下文切换
线程安全
多线程像单线程一样能够工作,不需要额外的操作。
全都线程安全的时候,速度会慢,成本大。
package com.hasson;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 描述: 第一种:运行结果出错。 演示计数不准确(减少),找出具体出错的位置。
*/
public class MultiThreadsError implements Runnable {
static MultiThreadsError instance = new MultiThreadsError();
int index = 0;
static AtomicInteger realIndex = new AtomicInteger();
static AtomicInteger wrongCount = new AtomicInteger();
static volatile CyclicBarrier cyclicBarrier1 = new CyclicBarrier(2);
static volatile CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2);
final boolean[] marked = new boolean[10000000];
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(instance);
Thread thread2 = new Thread(instance);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("表面上结果是" + instance.index);
System.out.println("真正运行的次数" + realIndex.get());
System.out.println("错误次数" + wrongCount.get());
}
@Override
public void run() {
marked[0] = true;
for (int i = 0; i < 10000; i++) {
try {
cyclicBarrier2.reset();
cyclicBarrier1.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
index++;
try {
cyclicBarrier1.reset();
cyclicBarrier2.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
realIndex.incrementAndGet();
synchronized (instance) {
if (marked[index] && marked[index - 1]) {
System.out.println("发生错误" + index);
wrongCount.incrementAndGet();
}
marked[index] = true;
}
}
}
}
对象发布和初始化的问题
什么是发布:
把一个对象用于超过这个类的方法使用,声明为pubic,return,参数,都是脱离了本类
逸出:
- 方法返回了private对象
public class MultiThreadsError3 {
public static void main(String[] args) {
System.out.println(new test().returnObject());
}
}
class test {
private Object o1;
public Object returnObject() {
o1 = new Object();
return o1;
}
}
- 还没有完成初始化(构造函数未执行完毕)
//初始化未完毕逸出
public class MultiThreadsError4 {
static Point point;
public static void main(String[] args) throws InterruptedException {
new PointMaker().start();
Thread.sleep(50); //这个时候结果是1,0,发生逸出。
Thread.sleep(150); //这个时候是1,1。所以时间不同,会出现不同的问题,这是一个线程不安全的问题。
if (point != null) {
System.out.println(point);
}
}
}
class Point {
private final int x, y;
public Point(int x, int y) throws InterruptedException {
this.x = x;
MultiThreadsError4.point = this;
Thread.sleep(100);
this.y = y;
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
'}';
}
}
class PointMaker extends Thread {
@Override
public void run() {
try {
new Point(1, 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 构造函数中新建线程
会认为已经新建好了,不管子线程的东西。-- >使用工厂模式修正
有人会说:不会有人写成这样的:但是有些库你看不到。构造函数里。可能使用多线程去加快速度
为什么多线程会带上性能问题
- 调度:上下文切换:
- 什么是上下文:保存线程,几微秒。挂起线程,保存状态,存在某处
- 缓存开销:调度之后,可能会缓存失效
- 何时会导致密集的上下文切换:抢锁,IO
- 协作:内存同步