线程的状态:
Java中 Thread.State (内部定义的枚举) 只要把State的枚举带印出来
package package1213;
public class ThreadStateDemo {
public static void main(String[] args) {
Thread.State[] values = Thread.State.values();
for (Thread.State state : values){
System.out.println(state);
}
}
}
NEW // 创建
RUNNABLE//就绪+运行 状态
BLOCKED//阻塞
WAITING//阻塞
TIMED_WAITING//阻塞
TERMINATED//停止
线程安全:进程运行的结果和预期的一致,就是线程安全
类/对象线程安全:该类或者该对象在使用时,不需要你再考虑线程问题,认为他线程安全
package package1213;
public class UnsafeThread {
private static int n = 0;
private static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
n++;
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[5];
for (int i = 0; i < 5; i++) {
Thread t = new MyThread();
t.start();
threads[i] = t;
}
for (int i = 0; i < 5; i++) {
threads[i].join();
}
System.out.println(n);
}
}
执行多次的结果
20782
22817
24204
不是我们预期25000
出现问题的原因:
1.有共享数据才有可能出现线程安全问题.
2.线程的调用是随时发生的,无法预测
这里就要提一下Java的内存分配了:
PC/栈(Java栈/本地方法栈) 私有的
堆/方法区/常量池 共享的
而这段代码中的静态变量n就是再方法区中
多线程出问题的原因
1.线程之间交错运行
2.内存区域的数据不相等
原子性
以下是原子的
int a = 10;原则性
… 除了 double/long
变量 = 常量的 操作都是原子的
非原子性
n++一定不是原子
因为,它划分几条操作 int tmp = n ; tmp = tmp + 1; n =tmp;
- 从内存把数据读到 CPU
- 进行数据更新
- 把数据写回到 CPU
这里没加到25000,就是因为原子性问题
比如线程一执行了1,2步,此时n加到了1000,这时候他的时间片到了,cpu不调度他了
然后线程二进来了执行了1,2步加到了1500,但是他成功在cpu调度时间内走到了第三步,把1500写回了cpu,然后退出
这时候线程一进来了,走第三步把1000写回cpu,这时候线程2就白忙活了
1.模型分为主内存和工作内存,
2.主内存只有一份,(虚拟真实的内存)
3工作内存,每个线程各有一份(虚拟真实的cpu内存)
4.线程不可以直接操作主内存中的数据
4.1.先load,把数据从之内存加载到工作内存
4.2.修改工作内存中的数据
4.3.合适的时候,把数据保存回主内存
Java内存区域划分是不同视角
大思路上,如何保证线程安全
- 如果涉及代码时,可以不进行数据共享,就尽量不数据共享 不用属性 + 静态属性没问题
- 如果非要共享数据,尽量使用数据的符本(复制出来的数据)/不可变对象 A传给B一份数据,如果B得到的数据只是一份复制,那数据其实也没有共享
- 确实要有数据共享了 做到三个保证: 原子/可见性/重排序
synchronized
synchronized用的锁是存在Java对象头里的。

synchronized void method() {}
==等价 void method(){
synchronized(this){}
}
//普通方法的锁,锁的是当前对象
synchronized static void smethod() {
synchronized(C.class){}
}
//锁的是这个类的对象
正确写法
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
synchronized (UnsafeThread.class){
//加个锁
n++;
}
}
}
737

被折叠的 条评论
为什么被折叠?



