下面验证上面三条结论
验证第一条结论:
packageSecond;public classMyObject {
}
packageSecond;public classService {public voidtestMethod1(MyObject object) {synchronized(object) {try{
System.out.println("testMethod1 ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("testMethod1 releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
packageSecond;public class ThreadA extendsThread {privateService service;privateMyObject object;publicThreadA(Service service, MyObject object) {super();this.service =service;this.object =object;
}
@Overridepublic voidrun() {super.run();
service.testMethod1(object);
}
}
packageSecond;public class ThreadB extendsThread {privateService service;privateMyObject object;publicThreadB(Service service, MyObject object) {super();this.service =service;this.object =object;
}
@Overridepublic voidrun() {super.run();
service.testMethod1(object);
}
}
packageSecond;public classRun1_1 {public static voidmain(String[] args) {
Service service= newService();
MyObject object= newMyObject();
ThreadA a= newThreadA(service, object);
a.setName("a");
a.start();
ThreadB b= newThreadB(service, object);
b.setName("b");
b.start();
}
}
同步的原因是使用了同一个“对象监视器“”。如果使用不同的“”对象监视器“”会出现什么效果呢?见下面
packageSecond;public classRun1_2 {public static voidmain(String[] args) {
Service service= newService();
MyObject object1= newMyObject();
MyObject object2= newMyObject();
ThreadA a= newThreadA(service, object1);
a.setName("a");
a.start();
ThreadB b= newThreadB(service, object2);
b.setName("b");
b.start();
}
}
packageSecond;public classRun1_2 {public static voidmain(String[] args) {
Service service= newService();
MyObject object1= newMyObject();
MyObject object2= newMyObject();
ThreadA a= newThreadA(service, object1);
a.setName("a");
a.start();
ThreadB b= newThreadB(service, object2);
b.setName("b");
b.start();
}
}
验证第2个结论
packageSecond;public classMyObject {synchronized public voidspeedPrintString() {
System.out.println("speedPrintString ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
System.out.println("-----------------");
System.out.println("speedPrintString releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
}
}
packageSecond;public classService {public voidtestMethod1(MyObject object) {synchronized(object) {try{
System.out.println("testMethod1 ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("testMethod1 releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
packageSecond;public class ThreadA extendsThread {privateService service;privateMyObject object;publicThreadA(Service service, MyObject object) {super();this.service =service;this.object =object;
}
@Overridepublic voidrun() {super.run();
service.testMethod1(object);
}
}
packageSecond;public class ThreadB extendsThread {privateMyObject object;publicThreadB(MyObject object) {super();this.object =object;
}
@Overridepublic voidrun() {super.run();
object.speedPrintString();
}
}
packageSecond;public classRun {public static void main(String[] args) throwsInterruptedException {
Service service= newService();
MyObject object= newMyObject();
ThreadA a= newThreadA(service, object);
a.setName("a");
a.start();
Thread.sleep(100);
ThreadB b= newThreadB(object);
b.setName("b");
b.start();
}
}
验证第3个结论
其他代码与第二个实验相同
packageSecond;public classMyObject {public voidspeedPrintString() {synchronized (this) {
System.out.println("speedPrintString ____getLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
System.out.println("-----------------");
System.out.println("speedPrintString releaseLock time="
+ System.currentTimeMillis() + " run ThreadName="
+Thread.currentThread().getName());
}
}
}
静态同步synchronized方法与synchronized(class)代码块
是对当前的*.java文件对应的class类进行持锁
packageSecond;public classService {synchronized public static voidprintA() {try{
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");
}catch(InterruptedException e) {
e.printStackTrace();
}
}synchronized public static voidprintB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}
}
packageSecond;public class ThreadA extendsThread {
@Overridepublic voidrun() {
Service.printA();
}
}
packageSecond;public class ThreadB extendsThread {
@Overridepublic voidrun() {
Service.printB();
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
ThreadA a= newThreadA();
a.setName("A");
a.start();
ThreadB b= newThreadB();
b.setName("B");
b.start();
}
}
下面展示synchronized关键字加到非static静态方法上的锁
packageSecond;public classService {synchronized public static voidprintA() {try{
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");
}catch(InterruptedException e) {
e.printStackTrace();
}
}synchronized public static voidprintB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}synchronized public voidprintC() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printC");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printC");
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printA();
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printB();
}
}
packageSecond;public class ThreadC extendsThread {privateService service;publicThreadC(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printC();
}
}
异步的原因是持有不同的锁,一个是对象锁,另外一个是class锁,而class锁可以对类的所有对象实例起作用,下面验证
packageSecond;public classService {synchronized public static voidprintA() {try{
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");
}catch(InterruptedException e) {
e.printStackTrace();
}
}synchronized public static voidprintB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printA();
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printB();
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
Service service1= newService();
Service service2= newService();
ThreadA a= newThreadA(service1);
a.setName("A");
a.start();
ThreadB b= newThreadB(service2);
b.setName("B");
b.start();
}
}
同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。下面测试
packageSecond;public classService {public static voidprintA() {synchronized (Service.class) {try{
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}public static voidprintB() {synchronized (Service.class) {
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printA();
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.printB();
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
Service service1= newService();
Service service2= newService();
ThreadA a= newThreadA(service1);
a.setName("A");
a.start();
ThreadB b= newThreadB(service2);
b.setName("B");
b.start();
}
}
数据类型String的常量池特性
packageSecond;public classService {public static voidprint(String stringParam) {try{synchronized(stringParam) {while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.print("AA");
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.print("AA");
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
Service service= newService();
ThreadA a= newThreadA(service);
a.setName("A");
a.start();
ThreadB b= newThreadB(service);
b.setName("B");
b.start();
}
}
出现这样的情况就是因为String的两个值都是AA,两个线程持有相同的锁,所以造成线程B不能执行。这就是String常量池所带来的问题。
因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他的,比如new object()实例化一个object对象,但它并不放入缓存中。
packageSecond;public classService {public static voidprint(Object object) {try{synchronized(object) {while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.print(newObject());
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.print(newObject());
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
Service service= newService();
ThreadA a= newThreadA(service);
a.setName("A");
a.start();
ThreadB b= newThreadB(service);
b.setName("B");
b.start();
}
}
交替打印是因为持有的锁不是同一个
同步synchronized方法无限等待与解决
同步方法容易造成死循环
packageSecond;public classService {synchronized public voidmethodA() {
Object object1= newObject();
System.out.println("methodA begin");boolean isContinueRun = true;while(isContinueRun) {
}
System.out.println("methodA end");
}synchronized public voidmethodB() {
Object object2= newObject();
System.out.println("methodB begin");
System.out.println("methodB end");
}
}
packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.methodA();
}
}
packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;
}
@Overridepublic voidrun() {
service.methodB();
}
}
packageSecond;public classRun {public static voidmain(String[] args) {
Service service= newService();
ThreadA athread= newThreadA(service);
athread.start();
ThreadB bthread= newThreadB(service);
bthread.start();
}
}
线程B永远得不到运行的机会,锁死了
packageSecond;public classService {public voidmethodA() {
Object object1= newObject();synchronized(object1) {
System.out.println("methodA begin");boolean isContinueRun = true;while(isContinueRun) {
}
System.out.println("methodA end");
}
}public voidmethodB() {
Object object2= newObject();synchronized(object2) {
System.out.println("methodB begin");
System.out.println("methodB end");
}
}
}