本文是参考此博主的内容进行测试学习:https://blog.csdn.net/acevd/article/details/80618741
1.测试多线程环境下,添加与不添加synchronized 锁的区别
测试代码new了10个线程,输出1-20 的数字,代码如下
public class LockTest {
static int num = 0;
@Test
public void test01() {
LockTest t = new LockTest();
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() {
public void run() {
add();
}
}).start();
}
}
private static void add() {
num += 1;
System.out.print(num+" ");
}
}
在方法add不加锁的情况,输出结果偶尔正确,偶尔错误。见下图:
但是在add方法加上synchronized关键字后,这个方法输出的就都是有序的了,代码如下
private static synchronized void add() {
num += 1;
System.out.print(num+" ");
}
结果如图:
引用原博主的话:
当我们使用了锁之后,运行程序,打印出来的结果和预期结果一样,为:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20。当使用锁控制的时候,线程操作将会变得有序。
这里还有一个公平锁和非公平锁的概念。多线程就像是很多人一起在食堂打饭,当你不进行锁控制的时候,所有线程就一起蜂拥而至去抢饭,非常的无序而且混乱;而使用非公平锁控制的时候,所有线程就开始“排队”了,一次只有一个线程能“从食堂大妈哪里打到饭”,其余的线程都会等待该线程处理完成后再一起抢那个“打饭的机会”;使用公平锁控制的时候,所有线程就变成了一群乖孩子,会井然有序地排队。1号同学先来的,先打饭,然后2号同学接着。
一句话概括就是:非公平锁是所有线程一起哄抢对象使用权;公平锁是按线程顺序,排队使用对象。
下面接着写另一个demo:此处代码完全来自原作者,记录下来是为了留个印记,方便后续查看
public class LockTest02 {
static Lock lock = new ReentrantLock(true);
/**
* synchronized锁
*
*/
static class SyncLocker{
public synchronized void print() {
System.out.println(Thread.currentThread().getName() + "获得锁");
}
}
/**
* ReentrantLock锁
*
*/
static class ReentrantLocker{
public void print() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "获得锁");
} finally {
lock.unlock();// 解锁
}
}
}
@Test
public void test() {
final SyncLocker syncLocker =new SyncLocker();
final ReentrantLocker syncLocker1 =new ReentrantLocker();
Runnable run=new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+"启动");
syncLocker1.print();
}
};
Thread[] threads =new Thread[10];
for(int i=0;i<10;i++) {
threads[i] =new Thread(run);
}
for(int i=0;i<10;i++) {
threads[i].start();
}
}
}
第一次是使用非公平锁结果如下:
0启动的,1先获得锁。
换成公平锁,结果如下:
完全按启动顺序获得锁。
感谢原博主愿意分享,大家一起学习,一起进步。