Java 锁
1.锁的对象是什么?
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象(可以理解为锁的类模板)。
对于同步方法块,锁是Synchonized括号里配置的对象
首先定义一个资源类
class South{
// synchronized 锁的对象是方法的调用者!、
// 两个方法用的是同一个锁,谁先拿到谁执行!
public synchronized void run1(){
System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
}
public synchronized void run2(){
System.out.println(Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
}
public void run3(){
System.out.println("无锁的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
}
public static synchronized void run4(){
System.out.println(Thread.currentThread().getName() + "成功创建!执行时间:" + System.currentTimeMillis() );
try {
TimeUnit.SECONDS.sleep(4);
System.out.println(Thread.currentThread().getName() + "线程暂停4秒!");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("静态syn的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
}
public static synchronized void run5(){
System.out.println("静态syn的方法被"+ Thread.currentThread().getName()+"执行了!执行时间:" + System.currentTimeMillis() );
}
}
普通方法进行加锁 对于普通同步方法,锁是当前实例对象
@Test
public void test1(){
South south = new South();
new Thread(() -> south.run1(),"A线程").start();
new Thread(() -> south.run2(),"B线程").start();
try { // 让主线程等待子线程,否则主线程(main线程)结束后,子线程的打印无法在控制台看到
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void test2(){
South south1 = new South();
South south2 = new South();
new Thread(() -> south1.run1(),"A线程").start();
new Thread(() -> south2.run2(),"B线程").start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果 | 总结 | 个人理解 | |
---|---|---|---|
test1 | A线程执行了!执行时间:1617866326536 # sleep(4) | 结果:B线程等待A线程结束后才执行 总结:多线程操作同一个资源,synchronized 锁的资源的调用者 即(当前实例对象) this,new South 的 south,两个线程是共用同一把锁,谁先得到锁,谁先执行 。
| A 首先获取的 this 并加锁,B 线程也尝试加锁,由于 syn 为独占锁,所以B 线程加锁失败被挂起,A 线程执行结束后被唤醒继续执行。 |
test2 | A线程执行了!执行时间:1617866385192 # A线程休眠中 | 结果:B线程等待A线程几乎是同时执行的 总结:多线程操作不同资源,线程之间的 synchronized 锁不影响(synchronized 锁的资源的调用者) | A 、B 两个线程获取的不是同一个资源 |
普通方法加锁与无锁方法对比
@Test
public void test3(){
South south = new South();
new Thread(() -> south.run1(),"A线程").start();
new Thread(() -> south.run3(),"B线程").start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
不同的资源对象,普通方法加锁、无锁与 静态方法 加锁方法对比
@Test
public void test4(){
South south1 = new South();
South south2 = new South();
South south3 = new South();
System.out.println(Thread.currentThread().getName()+ "执行了!执行时间:" +System.currentTimeMillis());
new Thread(() -> south1.run4(),"A线程").start();
new Thread(() -> south2.run3(),"B线程").start();
new Thread(() -> south3.run5(),"c线程").start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
同一的资源对象,普通与静态方法加锁
@Test
public void test5(){
South south1 = new South();
System.out.println(Thread.currentThread().getName()+ "执行了!执行时间:" +System.currentTimeMillis());
new Thread(() -> south1.run4(),"A线程").start();
new Thread(() -> south1.run2(),"B线程").start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}