初学多线程,肯定会接触同步。我们知道synchronized关键词可以修饰代码块,也可以修饰方法。那么具体修饰有什么区别呢?
一、含义
关于含义的资料随便一搜就是一大把,我在这里列出一篇文章的介绍:
synchronized 是同步锁,用来实现互斥同步。
在 Java 中,关键字 synchronized 可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作)。
synchronized 还可以保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代 volatile 功能,但是 volatile 更轻量,还是要分场景使用)。
参考链接:https://www.cnblogs.com/weixuqin/p/11429005.html
二、用法
synchronized可以修饰代码块、修饰静态方法、修饰非静态方法。
2.1 修饰代码块
修饰代码块的用法,是最常见的一种写法,其中的需要重点理解的是锁的含义。我们通过查看资料得知synchronized (A)括号肿的A有时候会用"this",有时候会用我们自己定义的一个对象。那么他们直接有什么区别呢?
如下图代码,用this锁。
class TestDiffObj implements Runnable {
@Override
public void run() {
obj2();
}
public void obj2() {
synchronized (this) {//这个this就是指当前对象(类的实例)
System.out.println(this.hashCode());
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
}① this:代表的是当前对象,也就是类的实例。
我们知道,下述新建了两个当前类的实例对象。
TestDiffObj testDiffObj1 = new TestDiffObj();
TestDiffObj testDiffObj2 = new TestDiffObj();如果,我们新建的线程用不同的对象实例,那么start后,就会有两个线程同时执行上述代码中的obj2()方法。虽然加锁了,但是锁对象不同,不能达到同步的目的,此时不会存在阻塞。
Thread thread1 = new Thread(testDiffObj1);
Thread thread2=new Thread(testDiffObj2);
thread1.start();
thread2.start(); 
但是,如果我们新建的线程用同一个实例对象,那么执行start()对象后,由于锁对象一致,那么会先执行完获得锁对象的线程,然后再执行另外一个线程。此时会有阻塞
Thread thread1 = new Thread(testDiffObj1);
Thread thread2 = new Thread(testDiffObj1);
thread1.start();
thread2.start();
② 自定义对象
使用自定义对象作为锁,其实和this本质是相同的。只要保证使用到的锁对象唯一,那么就能达到同步的目的,即会产生阻塞线程。

如果锁对象不唯一,则线程各自执行,不会产生阻塞。

2.2 修饰静态方法
修饰静态方法时,此时锁对象为所在类,即TestDiffObj .class即为锁。
class TestDiffObj implements Runnable {
Object object = new Object();
@Override
public void run() {
obj3();
}
public static synchronized void obj3() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}由于类锁是唯一的,此时不管新建的线程是否是同一个类的实例对象,执行起来都是同步


2.3 修饰非静态方法
修饰非静态方法,其实与使用this关键字的效果是相同的。
class TestDiffObj implements Runnable {
Object object = new Object();
@Override
public void run() {
obj4();
}
public synchronized void obj4() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
} 

三、写在最后
其实,Synchronized不管修饰代码块,静态方法还是非静态方法,最关键的还是搞清楚锁对象是否是一致的。
如果线程使用的锁一致,即多线程访问的是同一个对象,则能达到同步的效果;
否则线程则各自执行,不存在阻塞。
-----上述仅为我初学多线程的个人理解,欢迎小伙伴们一起交流