1.修饰静态方法和非静态方法
案例分析:
我们同时去操作一个int对象NUMBER,对它进行+1操作,我们看分别对非静态方法的锁定和静态方法的锁定有什么区别
1.1非静态方法
public class LockClass {
public static int NUMBER = 0; //待操作 的数字
public synchronized void noStaticMethod(String name) {
try {
if(name.equals("lockClassOne")) {
System.out.println("lockClassOne 锁定值后期望的值为 "+(NUMBER+1));
Thread.sleep(1000);
NUMBER += 1;
System.out.println("lockClassOne 实际操作后的值为"+(NUMBER));
}else{
Thread.sleep(500);
NUMBER += 1;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
下面是Main方法,分别开启10个线程去执行我的方法
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService poolExecutorOne = null;
ExecutorService poolExecutorTwo = null;
try {
final LockClass lockClassOne = new LockClass();
final LockClass lockClassTwo = new LockClass();
poolExecutorOne = Executors.newCachedThreadPool();
poolExecutorTwo = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
poolExecutorOne.submit(new Runnable() {
public void run() {
lockClassOne.noStaticMethod("lockClassOne");
}
});
}
for (int i = 0; i < 10; i++) {
poolExecutorTwo.submit(new Runnable() {
public void run() {
lockClassTwo.noStaticMethod("lockClassTwo");
}
});
}
} catch (Exception e) {
System.out.println("出现问题");
}finally {
if(poolExecutorOne!=null||poolExecutorOne.isShutdown()){
poolExecutorOne.shutdown();
}
if(poolExecutorTwo!=null||poolExecutorTwo.isShutdown()){
poolExecutorTwo.shutdown();
}
}
}
}
按道理来讲如果是同步的,那么每次lockClassOne的输出期望值和实际值一致
实际上我们可以看到不是这样的,说明了并未同步,每次锁定的是对象本身,本例中锁定的是lockClassOne和lockClassTwo,所以不同步
1.2修饰的是静态方法
//Main函数修改为调用静态方法
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService poolExecutorOne = null;
ExecutorService poolExecutorTwo = null;
try {
final LockClass lockClassOne = new LockClass();
final LockClass lockClassTwo = new LockClass();
poolExecutorOne = Executors.newCachedThreadPool();
poolExecutorTwo = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
poolExecutorOne.submit(new Runnable() {
public void run() {
// lockClassOne.noStaticMethod("lockClassOne");
lockClassOne.staticMethod("lockClassOne");
}
});
}
for (int i = 0; i < 10; i++) {
poolExecutorTwo.submit(new Runnable() {
public void run() {
// lockClassTwo.noStaticMethod("lockClassTwo");
lockClassTwo.staticMethod("lockClassTwo");
}
});
}
} catch (Exception e) {
System.out.println("出现问题");
}finally {
if(poolExecutorOne!=null||poolExecutorOne.isShutdown()){
poolExecutorOne.shutdown();
}
if(poolExecutorTwo!=null||poolExecutorTwo.isShutdown()){
poolExecutorTwo.shutdown();
}
}
}
}
LockClass添加静态方法
public class LockClass {
public static int NUMBER = 0;
public synchronized void noStaticMethod(String name) {
try {
if(name.equals("lockClassOne")) {
System.out.println("lockClassOne 锁定值后期望的值为 "+(NUMBER+1));
Thread.sleep(1000);
NUMBER += 1;
System.out.println("lockClassOne 实际操作后的值为"+(NUMBER));
}else{
Thread.sleep(500);
NUMBER += 1;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void staticMethod(String name) {
try {
if(name.equals("lockClassOne")) {
System.out.println("lockClassOne 锁定值后期望的值为 "+(NUMBER+1));
Thread.sleep(1000);
NUMBER += 1;
System.out.println("lockClassOne 实际操作后的值为"+(NUMBER));
}else{
Thread.sleep(500);
NUMBER += 1;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结论:
所以同步是正常的
synchronized锁定的非静态方法是锁定的对象本身,而synchronized锁定的静态方法是锁定的 Class本身
2.修饰变量,this,class的区别
2.1修饰变量
可以做到同步
2.2修饰this
synchronized (this){
就像绑定对应的实例对象
2.3修饰class
synchronized (LockClass.class){
和绑定static方法一样
3.修饰方法和修饰代码块的区别
synchronized方法,方法内部的所有代码块都锁定
synchronized代码,代码外的不会锁定
所以尽量减少锁定的区域,减少阻塞时间