java线程不安全详解,线程安全理解
00-1010线程的状态是枚举类型线程。状态
公共静态void main(String[]args){ for(Thread。状态状态:线程。state . values()){ system . out . println(state);}}新3360安排了工作,但还没开始。
RUNNABLE:可以工作。可以分为正在工作和即将开始工作。就绪状态
BLOCKED:这些都意味着排队等别的东西。
WAITING:这些都意味着排队等别的东西。
TIMED_WAITING:这些都意味着排队等别的事情。
终止:工作完成。
一、观察线程的所有状态
新的:Thread对象可用,但PCB不可用。
RUNNABLE:线程正在CPU上执行或即将在CPU上执行(PCB在就绪队列中,可以随时调度)
WAITING:wait方法导致
TIMED _ WAITING:sleep方法导致
阻塞:等待锁定原因
终结的:对象还在,但是PCB不见了。
public static void main(String[]args){ Thread t=new Thread(){ @ Override public void run(){ for(int I=0;i 100 _ 00I){ } } };System.out.println(线程启动前: t . getstate());t . start();while(t . isa live()){ system . out . println(线程运行: t . getstate());} System.out.println(线程结束后: t . getstate());}
00-1010不安全线程的原因
线程被抢先执行。
线程不安全是所有邪恶的根源。线程之间的调度完全是内核的责任,这在用户代码中是无法察觉和控制的。线程之间,谁先执行,谁后执行,谁在哪里下CPU就执行,这个过程是用户无法控制和感知的。
自动增量操作不是原子的。
它可以一次分成三个步骤。
将内存中的数据读入CPU
将数据1放入CPU
将计算的数据写回到存储器中。
如果两个线程串行执行,结果是2。
如果两个线程并行执行,当线程1执行到一半时,该线程也会执行。此时递增两次,结果却是1。
需要保证线程1保存,线程2再次加载,然后计算结果才是正确的。
多个线程试图修改同一个变量。
如果一个线程修改了一个变量,那么它就是线程安全的。
如果多个线程读取同一个变量,那么它是线程安全的。
如果多线程修改不同的变量。线程安全
内存可见性导致线程安全问题。
指令重新排序
Java编译器在编译代码时,会对指令进行优化,调整指令顺序,保证原有逻辑不变,提高程序运行效率。
00-1010锁同步
开锁
静态类计数器{ public int count=0;public void increase(){ count;} }公共静态void main(String[] args)抛出interrupted exception { Counter Counter=new Counter();Thread t1=new Thread(){ @ Override public void run(){ for(int I=0;液性指数
t; 50000; i++){ counter.increase(); } } }; Thread t2 = new Thread(){ @Override public void run() { for (int i = 0; i < 50000; i++){ counter.increase(); } } }; t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(counter.count); }
已加锁
static class Counter{ public int count = 0; synchronized public void increase(){ count++; } } public static void main(String[] args) throws InterruptedException { Counter counter = new Counter(); Thread t1 = new Thread(){ @Override public void run() { for (int i = 0; i < 50000; i++){ counter.increase(); } } }; Thread t2 = new Thread(){ @Override public void run() { for (int i = 0; i < 50000; i++){ counter.increase(); } } }; t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(counter.count); }
此处的synchronized就是针对counter这个对象来加锁,进入increase方法内部,就把加锁状态设为ture,increase方法退出之后,就把加锁状态设为false,如果某个线程已经把加锁状态设为ture,此处的其他的线程尝试去加锁,就会阻塞
synchronized的特性——刷新内存
synchronized 的工作过程:
1. 获得互斥锁
2. 从主内存拷贝变量的最新副本到工作的内存
3. 执行代码
4. 将更改后的共享变量的值刷新到主内存
5. 释放互斥锁
synchronized的特性——互斥
public static void main(String[] args) { Object locker = new Object(); Thread t1 = new Thread(){ @Override public void run() { Scanner scanner = new Scanner(System.in); synchronized (locker) { System.out.println("输入一个整数"); int num = scanner.nextInt(); System.out.println("num= " + num); } } }; t1.start(); Thread t2 = new Thread(){ @Override public void run() { while (true){ synchronized (locker){ System.out.println("线程2获取到锁"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; t2.start(); }
一旦线程一获取到锁,并且没有释放的话,线程2就会一直在锁这里阻塞等待
public static void main(String[] args) { Object locker1 = new Object(); Object locker2 = new Object(); Thread t1 = new Thread(){ @Override public void run() { Scanner scanner = new Scanner(System.in); synchronized (locker1) { System.out.println("输入一个整数"); int num = scanner.nextInt(); System.out.println("num= " + num); } } }; t1.start(); Thread t2 = new Thread(){ @Override public void run() { while (true){ synchronized (locker2){ System.out.println("线程2获取到锁"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; t2.start(); }
不是同一把锁,就不回出现竞争,就没有互斥了。
public static void main(String[] args) { Object locker1 = new Object(); Object locker2 = new Object(); Thread t1 = new Thread(){ @Override public void run() { Scanner scanner = new Scanner(System.in); synchronized (locker1.getClass()) { System.out.println("输入一个整数"); int num = scanner.nextInt(); System.out.println("num= " + num); } } }; t1.start(); Thread t2 = new Thread(){ @Override public void run() { while (true){ synchronized (locker2.getClass()){ System.out.println("线程2获取到锁"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; t2.start(); }
这个代码中,两个线程都在针对locker1和locker2的类对象进行竞争,此处的locker1和locker2的类型都是Object,对应的对象都是相同的对象。
到此这篇关于Java线程安全状态专题解析的文章就介绍到这了,更多相关Java 线程安全内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。