如何解决线程不安全问题呢?
线程安全问题存在,必然会引起很多问题。那么本节就来讲讲,如何解决线程安全问题呢?
1、synchronized
synchronized关键字,就是java用来控制线程同步的,比如上节的最后举例中,在代码中加入共享变量后,使用多线程调用时,会产生count数据产生偏差问题。
此关键字,一般是加在方法上的如:
public static int count =0; public static void main(String[] args){ for (int i = 0; i <3 ; i++) { new Thread(new Runnable() { @Override public void run() { System.out.println(getcountNum(30)); System.out.println("count为:"+count); try{ Thread.sleep(1); }catch (Exception e){ e.printStackTrace(); } } }).start(); } } public static synchronized int getcountNum(int j){ int i =1; count++; j=j+3; return j; }
运行结果为:
此方法就变成了一个线程安全的方法了。
首先synchronized锁的是括号里的对象,而不是代码,其次,对于非静态的synchronized方法,锁的是对象本身也就是this。
当synchronized锁住一个对象之后,别的线程如果想要获取锁对象,那么就必须等这个线程执行完释放锁对象之后才可以,否则一直处于等待状态。
虽然加synchronized关键字,可以让我们的线程变得安全,但是我们在用的时候,也要注意缩小synchronized的使用范围,如果随意使用时很影响程序的性能,别的对象想拿到锁,结果你没用锁还一直把锁占用,这样就有点浪费资源。
也就是说:1.非static方法,同步锁是this。2.static方法,使用当前方法所在类的字节码对象(Apple.class)是同步锁
2、lock
先来说说它跟synchronized有什么区别吧,Lock是在Java1.6被引入进来的,Lock的引入让锁有了可操作性,什么意思?就是我们在需要的时候去手动的获取锁和释放锁,甚至我们还可以中断获取以及超时获取的同步特性,但是从使用上说Lock明显没有synchronized使用起来方便快捷。我们先来看下一般是如何使用的:
public static void main(String[] args){ for (int i = 0; i <3 ; i++) { new Thread(new Runnable() { @Override public void run() { getcountNum(Thread.currentThread(),30); try{ Thread.sleep(1); }catch (Exception e){ e.printStackTrace(); } } }).start(); } } private static Lock lock = new ReentrantLock(); public static int getcountNum(Thread a,int j){ lock.lock(); int i =1; count++; System.out.println("当前是线程:"+a.getName()+",count="+count); j=j+3; lock.unlock(); return j; }
上次分享线程不安全的文章中,得到的count全是3,加上锁后得到结果是:
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
html兼容IE中的说明