0002-多线程线程安全
Synchronized
1.同步函数用的锁是this
package cn.yorz.testthread; /** * * @author Administrator * 验证同步函数用的this * */ class Ticket implements Runnable { private int tick = 100; Object obj = new Object(); boolean flag = true; public void run(){ if(flag){ while(true) synchronized(this){ //注意这里的锁要一致 //跟show()函数一样都是一个锁,show()锁是本身所以是this //同步的前提是:1、两个及其以上的线程;2、锁一样 if(tick>0){ try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"同步代码块"+tick--); } } }else{ while(true) show(); } } public synchronized void show(){ //锁是this if(tick>0){ try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"同步函数...."+tick--); } } } public class TestSynchronizedFunction{ public static void main(String[] args){ //验证数据并没有冲突 于是用的就是this锁 Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(Exception e){} t.flag = false; t2.start(); } }
2,静态方法用的锁是class对象
多线程死锁问题
package cn.yorz.testthread; /** * * @author Administrator * 多线程死锁问题,多个锁对象才能产生死锁现象
*/ public class DeadLock implements Runnable{ private int flag = 1; private Object obj1 = new Object(), obj2 = new Object(); public void run() { System.out.println(Thread.currentThread().getName()+":flag=" + flag); if (flag == 1) { synchronized (obj1) { System.out.println("1:"+Thread.currentThread().getName()+"我已经锁定obj1,休息0.5秒后锁定obj2去!"); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (obj2) { System.out.println(Thread.currentThread().getName()+":1"); } } } if (flag == 0) { synchronized (obj2) { System.out.println("0:"+Thread.currentThread().getName()+"我已经锁定obj2,休息0.5秒后锁定obj1去!"); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized (obj1) { System.out.println(Thread.currentThread().getName()+":0"); } } } } public static void main(String[] args) { DeadLock deadLock = new DeadLock(); Thread thread01 = new Thread(deadLock); Thread thread02 = new Thread(deadLock); System.out.println("线程开始喽!"); thread01.start(); thread02.start(); try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } deadLock.flag=0; } }
java内存模型
1.多线程的三大特性
原子性
有效性
可见性
2.java内存模型和java内存结构
java内存模型:jmm,与线程的可见性相关。
java内存结构:jvm,堆和栈
java内存模型详解
JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
Volatile关键字
作用:保证线程之间可见,但不保证原子性。既:一个线程修改了一个共享变量的值可以立马通知给另一个线程。
package cn.yorz.testthread; /** * * @author Administrator * 测试volatile关键字 */ //线程 class VolatileThread extends Thread{ private volatile boolean flag=true; //如果没有volatile关键字,此段程序有无法终止的可能 public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } @Override public void run() { System.out.println(Thread.currentThread().getName()+"线程开始执行"); while(flag) { } System.out.println(Thread.currentThread().getName()+"线程执行结束"); } } public class TestVolatile { public static void main(String[] args) { VolatileThread t1=new VolatileThread(); t1.start();
//此段代码注释掉可以执行结束,不注释掉要加volatile修饰flag,否则无法停止 try { Thread.sleep(3000); t1.setFlag(false); System.out.println(Thread.currentThread().getName()+"已经修改flag的值"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
System.out.println(t1.getName()+"flag的值"+t1.isFlag()); } }
atomicinteger原子类
public class TestVolatileNotAtomic extends Thread{ private volatile static int count=0; private static AtomicInteger atomicInteger=new AtomicInteger(0); //原子类 @Override public void run() { for (int i = 0; i < 1000; i++) { count++; atomicInteger.incrementAndGet();//自增 } System.out.println(Thread.currentThread().getName()+"count---"+count); System.out.println(Thread.currentThread().getName()+"atomicInteger---"+atomicInteger.get()); //得到结果 } public static void main(String[] args) { //创建十个线程 TestVolatileNotAtomic[] testVolatileNotAtomics=new TestVolatileNotAtomic[10]; for (int i = 0; i < testVolatileNotAtomics.length; i++) { testVolatileNotAtomics[i]=new TestVolatileNotAtomic(); } //遍历start for (int i = 0; i < testVolatileNotAtomics.length; i++) { testVolatileNotAtomics[i].start(); } } }