在使用多线程的场合中,线程安全是需要考虑的一个问题。
线程安全问题主要需要考虑一下几点:
- 存在共享数据(全局变量,共享资源等)
- 多线程场合,大量线程访问或者操作共享数据
我们需要达到的效果:
当多个线程在运行时,可能会有同时访问共享数据的情况发生,需要保证同一个时刻有且只有一个线程在操作共享数据,其他线程此时处在等待状态。
思路:
增加一个互斥锁,一个线程在访问的共享数据操作上加一个互斥锁,同一时刻,其他线程只能等待,等待该线程释放互斥锁,才可访问。
关键字:
synchronized,保证同一时刻只有一个线程可以执行某个方法或者代码块。
synchronized使用的几种场合:
1.修饰实例方法
//实例方法,锁住的是该类的实例对象
public synchronized void method(){
//do something
//...
}
2.修饰静态方法
//静态方法,锁住的是类对象
public static synchronized void method(){
//do something
//...
}
3.修饰代码块
//锁住类的实例对象
synchronized(this){
//do something
//...
}
//锁住类对象
synchronized(Demo.class){
//do something
//...
}
//锁住一个Object对象
private static final Object mLock = new Object();
synchronized(mLock ){
//do something
//...
}
关于synchronized失效不起作用的问题分析:
代码如下:
private int count = 0;
new Thread(new Runnable() {
@Override
public void run() {
synchronized(this){
count = 111;
count = 222;
Log.i(TAG,"count=" + count)
}
}
}).start();
上述的synchronized关键字可能会失效,创建多线程是同步的this,可能不是同一个对象,而可能导致的结果是打印:
demo,count=111
demo,count=111
demo,count=222
demo,count=111
修正方法如下:
private static final Object mLock = new Object();
private int count = 0;
new Thread(new Runnable() {
@Override
public void run() {
synchronized(this){
count = 111;
count = 222;
Log.i(TAG,"count=" + count)
}
}
}).start();