大家有没有想过一个问题,Java中的++ *** 作是不是线程安全的呢,也就是说在多线程情况下,多个线程一起去执行++ *** 作,得到的结果会不会是我们所预期的结果呢,可以写个demo去验证一下。
public static int count = 0; public static void main(String[] args) { for (int j = 0; j < 10000; j++) { new Thread(new Runnable() { @Override public void run() { add(); } }).start(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } public static void add(){ count++; } 复制代码
最后的执行结果如下图:
很明显,Java中的++ *** 作,并不是线程安全的。 这就涉及到了多线程环境下,如何才能保证在 *** 作同一个变量或者方法时保证线程安全。
二、Synchronized 什么是Synchronized?Synchronized关键字,就是利用一个特定的对象设置一个锁(lock),在多线程并发访问的时候,只允许一个线程可以获得这个锁,并执行代码,等到代码执行完毕后,释放锁,再继续由其他线程争抢。
Synchronized的使用我们可以稍微改造一下上面的demo,让++ *** 作变成线程安全的。
public static int count = 0; public static void main(String[] args) { for (int j = 0; j < 10000; j++) { new Thread(new Runnable() { @Override public void run() { add(); } }).start(); } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count); } public synchronized static void add(){ count++; } 复制代码
只是做个一个很小的改动,就是在add()方法中加入synchronized关键字,看一下执行结果:
多次执行得到的结果都是10000,是符合我们预期的,add()方法也变成了一个线程安全的方法。
Synchronized的使用场景Synchronized有三种不同的使用场景,同时也对应着不同的锁对象。
1.Synchronized代码块将上面demo的add()方法改造一下
public static void add(){ Object o = new Object(); //锁对象 synchronized (o){ count++; } } 复制代码
定义一个Object对象,将Object作为锁对象,只会有一个线程获得这个锁对象,执行++ *** 作,别的线程需要等待锁对象被释放时候,争抢这个锁对象,获得锁对象的才能继续执行++。
2.Synchronized方法public synchronized void add(){ ... ... } 复制代码
在这个add()方法的锁对象又是什么呢,很明显,就是this当前对象,线程获得的是当先对象。
3.Synchronized静态方法public synchronized static void add(){ count++; } 复制代码
最后一种就是demo中的add()方法,这时的锁对象就是当前类的字节码对象,因为是静态方法,静态方法是属于这个类的,所以锁对象就是当前类的字节码对象。
总结Synchronized使用在代码块中,锁对象可以是任意对象。 Synchronized使用在方法中,锁对象为当前对象this。 Synchronized使用在静态方法中,锁对象为当前类的字节码对象。 复制代码三、常见的使用Synchronized类
Vector是线程安全的,ArrayList、linkedList是线程不安全的 Properties是线程安全的,HashSet、TreeSet是不安全的 StringBuffer是线程安全的,StringBuilder是线程不安全的 HashTable是线程安全的,HashMap是线程不安全的
四、总结Synchronized虽然可以保证多线程共享数据的数据安全,但是如果使用不当,线程长期持有锁对象,未及时得到释放,很容易造成死锁问题, 而且在性能问题上,Synchronized对性能也会有一定的影响,所以请慎用Synchronized。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)