synchronized 到底锁的是谁?
修饰方法:
1、静态方法
2、非静态方法,锁住的是方法的调用者
修饰代码块
流程:
1、线程A先拿到synModel对象然后给这个 synModel对象加上锁–接着等3s执行输出结束
2、线程B等1s后运行,此时 synModel对象 已经被 A拿到,所以他只能等待 等3s后,线程A释放 synModel对象,然后获取对象执行输出结束
public class SynchronizedTest {
public static void main(String[] args) throws InterruptedException {
SynModel synModel = new SynModel();
new Thread(()->{
synModel.fun1();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
synModel.fun2();
},"B").start();
}
}
class SynModel{
public synchronized void fun1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1...");
}
public synchronized void fun2(){
System.out.println("2...");
}
}
注意:下面这种情况是不会排队的,因为锁的是实例。
public class SynchronizedTest {
public static void main(String[] args) throws InterruptedException {
SynModel synModel1 = new SynModel();
SynModel synModel2 = new SynModel();
new Thread(()->{
synModel1.fun1();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
synModel2.fun2();
},"B").start();
}
}
class SynModel{
public synchronized void fun1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1...");
}
public synchronized void fun2(){
System.out.println("2...");
}
}
只是把SynModel中的方法变成了静态的,注意此时锁住的是 SynModel这个类,不是锁的实例。会排队 先输出1后输出2
public class SynchronizedTest {
public static void main(String[] args) throws InterruptedException {
SynModel synModel1 = new SynModel();
SynModel synModel2 = new SynModel();
new Thread(()->{
synModel1.fun1();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
synModel2.fun2();
},"B").start();
}
}
class SynModel{
public static synchronized void fun1() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1...");
}
public static synchronized void fun2(){
System.out.println("2...");
}
}
synchronized (this){}
锁住的是SynModel这个对象。可以看到循环的五次都是同一个SynModel对象。所以五个线程 某个时刻只能有一个线程拿到这个SynModel对象 这个资源。
每个线程会依次输出start end
public class SynchronizedTest {
public static void main(String[] args) {
final SynModel synModel = new SynModel();
for (int i = 0; i < 5; i++) {
synModel.fun3();
}
}
}
class SynModel{
public void fun3(){
synchronized (this){
System.out.println("start");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
}
如果把对象放在循环里面,此时就是五个线程拿五个资源了。并没有去争夺资源
public class SynchronizedTest {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
final SynModel synModel = new SynModel();
new Thread(()->{
synModel.fun3();
}).start();
}
}
}
class SynModel{
public void fun3(){
synchronized (this){
System.out.println("ThreadName:"+Thread.currentThread().getName()+"start");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadName:"+Thread.currentThread().getName()+"end");
}
}
}
锁住SynModel.class 此时五个线程就会竞争,因为锁住的是 SynModel这个类,而不是实例对象了。
public class SynchronizedTest {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
final SynModel synModel = new SynModel();
new Thread(()->{
synModel.fun3();
}).start();
}
}
}
class SynModel{
public void fun3(){
synchronized (SynModel.class){// this SynModel.class
System.out.println("ThreadName:"+Thread.currentThread().getName()+"start");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadName:"+Thread.currentThread().getName()+"end");
}
}
}