释放双眼,带上耳机,听听看~!
synchronized
- synchronized可以修饰方法和代码块
- 多线程在执行synchronized方法时线程会阻塞
- synchronized可以保证线程的原子性
volatile
- volatile的性能比synchronized要高
- volatile只能修饰变量
- 多线程访问volatile时线程不会阻塞
- volatile不能保证线程的原子性
线程原子性是指不能在被拆分的操作。在说的直白点就是我们知道线程在执行时是需要一个前提条件的那就是需要获取到系统CPU的执行资格,虽然线程获取到了执行资格但CPU也可以随时切换,不管线程是否执行完毕。线程原子性就是说如果线程已经获取到了CPU的执行资格,如果线程在没有执行完时,任何线程是不能够中断的。
下面的事例我们演示一下volatile关键字为什么不支持线程原子性。
/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo extends Thread {
public volatile static int count;
private static void count() {
for (int i = 0; i < 100; i++) {
count++;
}
System.out.println(String.format("count: %s thread: %s", count, Thread.currentThread().getName()));
}
@Override
public void run() {
count();
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) throws InterruptedException {
Userinfo[] userinfos = new Userinfo[100];
for (int i = 0; i < 100; i++) {
userinfos[i] = new Userinfo();
}
for (int i = 0; i < 100; i++) {
userinfos[i].start();
}
}
}
count: 9200 thread: Thread-66
count: 9600 thread: Thread-62
count: 9800 thread: Thread-60
count: 9700 thread: Thread-61
count: 9900 thread: Thread-59
count: 10000 thread: Thread-58
count: 9300 thread: Thread-65
count: 9400 thread: Thread-64
count: 10000 thread: Thread-63
我们看结果显示Thread-58和线程Thread-63输出count都是10000。这显然是不正确的。原因就是volatile关键字是不支持原子性也不支持同步性的。如果我们把count()方法添加synchronized关键字,那输出结果就是线程安全的了。
/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo extends Thread {
public volatile static int count;
private synchronized static void count() {
for (int i = 0; i < 100; i++) {
count++;
}
System.out.println(String.format("count: %s thread: %s", count, Thread.currentThread().getName()));
}
@Override
public void run() {
count();
}
}
count: 9400 thread: Thread-7
count: 9500 thread: Thread-5
count: 9600 thread: Thread-6
count: 9700 thread: Thread-4
count: 9800 thread: Thread-3
count: 9900 thread: Thread-1
count: 10000 thread: Thread-2
我们看结果是线程安全的了。