同步分为 同步方法 和 同步块 两种方式。
变量分为 实例变量(不带static的变量) 和 类变量(带static的变量)。
【当锁定static变量的时候,由于static变量只有一份拷贝,所以此时锁定的也是类对象】
下面的写法都是锁定类对象。在下面的例子中是锁定的StaticSynchronized这个类。
测试代码:
package com.pkk.javaknow.synchronized_demo;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author kunzai
* @version V1.0
* @Title: myknow
* @Package com.pkk.javaknow.synchronized_demo
* @Description: <静态类的锁的测试>
* @date 2018/5/18 9:28
*/
public class StaticSynchronized {
private static Object object = new Object();
private static long sleepTime = 3000;
public static synchronized void synchronizedMethod1() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "synchronizedMethod1:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "synchronizedMethod1:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static void synchronizedMethod2() throws InterruptedException {
synchronized (StaticSynchronized.class) {
System.out.println(Thread.currentThread().getName() + "synchronizedMethod2:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "synchronizedMethod2:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
public static void synchronizedMethod3() throws InterruptedException {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + "synchronizedMethod3:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "synchronizedMethod3:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
public static void synchronizedMethod4() throws ClassNotFoundException, InterruptedException {
synchronized (Class.forName("com.pkk.javaknow.synchronized_demo.StaticSynchronized")) {
System.out.println(Thread.currentThread().getName() + "synchronizedMethod4:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "synchronizedMethod4:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
public static void main(String[] args) throws InterruptedException {
/**
* 核心线程数--不受超时时间影响-一直存在
*/
int corePoolSize = 2;
/**
*最大线程数--当队列为LinkedBlockingDeque时,LinkedBlockingDeque根本不受最大线程数影响,超出会加入队列中,如果设置了队列数限制(本次设置为10),超过报错
*/
int maximumPoolSize = 6;
/**
* 超时时间,新创建的不在核心线程中的超过5秒就清除掉
*/
long keepAliveTime = 5;
/**
* 最大等待队列数
*/
int maxWaitQue = 10;
/**
* 执行次数
*/
int forCnt = 3;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque(maxWaitQue));
for (int i = 0; i < forCnt; i++) {
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
synchronizedMethod1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
synchronizedMethod2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
synchronizedMethod3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
synchronizedMethod4();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
}
threadPoolExecutor.shutdown();
}
}
测试结果:
pool-1-thread-1synchronizedMethod1:is Run;2018-05-18 14:58:55
pool-1-thread-1synchronizedMethod1:is End;2018-05-18 14:58:58
pool-1-thread-1synchronizedMethod3:is Run;2018-05-18 14:58:58
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:58:58
pool-1-thread-1synchronizedMethod3:is End;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod1:is Run;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod1:is End;2018-05-18 14:59:04
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:59:04
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:07
pool-1-thread-2synchronizedMethod3:is Run;2018-05-18 14:59:07
pool-1-thread-1synchronizedMethod4:is Run;2018-05-18 14:59:07
pool-1-thread-2synchronizedMethod3:is End;2018-05-18 14:59:10
pool-1-thread-1synchronizedMethod4:is End;2018-05-18 14:59:10
pool-1-thread-2synchronizedMethod4:is Run;2018-05-18 14:59:10
pool-1-thread-2synchronizedMethod4:is End;2018-05-18 14:59:13
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:59:13
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:16
pool-1-thread-2synchronizedMethod3:is Run;2018-05-18 14:59:16
pool-1-thread-1synchronizedMethod1:is Run;2018-05-18 14:59:16
pool-1-thread-2synchronizedMethod3:is End;2018-05-18 14:59:19
pool-1-thread-1synchronizedMethod1:is End;2018-05-18 14:59:19
pool-1-thread-2synchronizedMethod4:is Run;2018-05-18 14:59:19
pool-1-thread-2synchronizedMethod4:is End;2018-05-18 14:59:22
总结:
从上面测试结果可以看出,方法三是可以和其他三个方法中的任何一个方法并行执行,因为方法三锁定的是Object这个静态类对象而不是锁定的StaticSynchronized类,他们挣得不是同一个锁,所以可以并行执行,但是方法1和2和4中任何一个方法不可以并行执行,因为他们锁定的是StaticSynchronized类对象,这个没有释放,另一个不可以执行。
这种情况下,如果有一个线程thread 访问了这3个方法中的任何一个, 在同一时间内其它的线程都不能访问这3个方法。(注意,在这类里面方法3中锁定的是object对象,不是本类对象。)
总结一下:
synchronized可以修饰方法,可以修饰变量,方法和变量都可以是静态的【类方法类变量】,或者是非静态【实例方法实例变量】的。
锁定实例对象
synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。
同步方法不会影响该类中的其他方法去执行
测试代码
package com.pkk.javaknow.synchronized_demo;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author peikunkun
* @version V1.0
* @Title: myknow
* @Package com.pkk.javaknow.synchronized_demo
* @Description: <方法锁>
* @date 2018/5/18 11:55
*/
public class MethodSynchronized {
private static long sleepTime = 3000;
public static void main(String[] args) throws InterruptedException {
/**
* 核心线程数--不受超时时间影响-一直存在
*/
int corePoolSize = 2;
/**
*最大线程数--当队列为LinkedBlockingDeque时,LinkedBlockingDeque根本不受最大线程数影响,超出会加入队列中,如果设置了队列数限制(本次设置为10),超过报错
*/
int maximumPoolSize = 6;
/**
* 超时时间,新创建的不在核心线程中的超过5秒就清除掉
*/
long keepAliveTime = 5;
/**
* 最大等待队列数
*/
int maxWaitQue = 10;
/**
* 执行次数
*/
int forCnt = 1;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque(maxWaitQue));
for (int i = 0; i < forCnt; i++) {
MethodSynchronized methodSynchronized = new MethodSynchronized();
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
methodSynchronized.methodSynchronized3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
methodSynchronized.methodSynchronized2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
try {
methodSynchronized.methodSynchronized1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
threadPoolExecutor.shutdown();
}
public synchronized void methodSynchronized1() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "methodSynchronized1:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "methodSynchronized1:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public void methodSynchronized3() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "methodSynchronized3:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "methodSynchronized3:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public void methodSynchronized2() throws InterruptedException {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "methodSynchronized2:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
Thread.sleep(sleepTime);
System.out.println(Thread.currentThread().getName() + "methodSynchronized2:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
}
运行结果:
pool-1-thread-1methodSynchronized3:is Run;2018-05-18 17:12:30
pool-1-thread-2methodSynchronized2:is Run;2018-05-18 17:12:30
pool-1-thread-1methodSynchronized3:is End;2018-05-18 17:12:33
pool-1-thread-2methodSynchronized2:is End;2018-05-18 17:12:33
pool-1-thread-1methodSynchronized1:is Run;2018-05-18 17:12:33
pool-1-thread-1methodSynchronized1:is End;2018-05-18 17:12:36
可以看出,不带同步的方法和一个同步的方法可以同时执行,但是此时锁定了本对象,另一个带有同步的方法就不可以执行,需要等待这个所释放之后才可以执行。
也就是说synchronize修饰的方法和 synchronize(this) 都是锁住自己本身的对象 而synchronized(*.class)是锁住加载类对象,synchronized(object)是锁住object对象吧