标签:ati 错误 灵活 div 异常 star 赋值 except read
一、线程安全问题
多线程操作各自线程创建的资源的时候,不存在线程安全问题。但多线程操作同一个资源的时候就会出现线程安全问题。下例为两个线程操作同一个name资源时发生的问题。
class TestSyn { public static void main(String[] args) throws Exception { Resource resource = new Resource(); new Thread() { @Override public void run() { while (true) { r.sayb(); } } }.start(); new Thread() { @Override public void run() { while (true) { r.sayq(); } } }.start(); } } class Resource { private String name; public void sayb() { name = "bbb"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb } public void sayq() { name = "qqqqqq"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb } } /** * Thread-1qqqqqq Thread-1qqqqqq Thread-0qqqqqq //其中一段错误信息,Thread-0线程也打印了qqqqqq Thread-0bbb Thread-0bbb */
问题出现过程:
Thread-0获取执行权执行name="bbb"。
Thread-1获得执行权执行name="qqqqqq"。
Thread-0重新获得执行权执行打印指令,这时Thread-0就打印出了qqqqqq。
二、synchronized代码块
如果name赋值,打印name是一个原子操作就可以避免线程安全问题。
java中synchronized可以标记一段代码,达到原子操作的效果。
synchronized标记代码有两种方式:
//synchronized代码块 class Resource { private String name; public void sayb() { synchronized (this){ name = "bbb"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb } //...其他代码 } public void sayq() { synchronized (this){ name = "qqqqqq"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb } //...其他代码 } }
//synchronized方法 class Resource { private String name; public synchronized void sayb() { name = "bbb"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb //...其他代码 } public synchronized void sayq() { name = "qqqqqq"; System.out.println(Thread.currentThread().getName() + name);//Thread-0打印bbb //...其他代码 } }
上例中两个线程执行的是同一个对象的方法,因此他们抢夺同一个锁,一个线程执行的时候,另一个线程阻塞。
两种方法有些不同点:
注意:synchronized不会死锁,异常抛出时虚拟机会释放锁。
标签:ati 错误 灵活 div 异常 star 赋值 except read
原文地址:https://www.cnblogs.com/liuboyuan/p/10083807.html