下面验证上面三条结论

验证第一条结论:

package Second;

public class MyObject {
}
package Second;

public class Service {

    public void testMethod1(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();
}
}
} }
package Second;

public class ThreadA extends Thread {

    private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class ThreadB extends Thread {
private Service service;
private MyObject object; public ThreadB(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class Run1_1 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object);
b.setName("b");
b.start();
} }

同步的原因是使用了同一个“对象监视器“”。如果使用不同的“”对象监视器“”会出现什么效果呢?见下面

package Second;

public class Run1_2 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }
package Second;

public class Run1_2 {

    public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }

验证第2个结论

package Second;

public class MyObject {
synchronized public void speedPrintString() {
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());
}
}
package Second;

public class Service {

    public void testMethod1(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();
}
}
} }
package Second;

public class ThreadA extends Thread {

    private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second;

public class ThreadB extends Thread {
private MyObject object; public ThreadB(MyObject object) {
super();
this.object = object;
} @Override
public void run() {
super.run();
object.speedPrintString();
}
}
package Second;

public class Run {

    public static void main(String[] args) throws InterruptedException {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); Thread.sleep(100); ThreadB b = new ThreadB(object);
b.setName("b");
b.start();
} }

验证第3个结论

其他代码与第二个实验相同

package Second;

public class MyObject {
public void speedPrintString() {
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类进行持锁

package Second;

public class Service {

    synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second;

public class ThreadA extends Thread {
@Override
public void run() {
Service.printA();
} }
package Second;

public class ThreadB extends Thread {
@Override
public void run() {
Service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        ThreadA a = new ThreadA();
a.setName("A");
a.start(); ThreadB b = new ThreadB();
b.setName("B");
b.start(); } }

下面展示synchronized关键字加到非static静态方法上的锁

package Second;

public class Service {

    synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} synchronized public void printC() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printC");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printC");
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
} }
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class ThreadC extends Thread {

    private Service service;

    public ThreadC(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printC();
}
}

异步的原因是持有不同的锁,一个是对象锁,另外一个是class锁,而class锁可以对类的所有对象实例起作用,下面验证

package Second;

public class Service {

    synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }

同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。下面测试

package Second;

public class Service {

    public static void printA() {
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 void printB() {
synchronized (Service.class) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }

数据类型String的常量池特性

package Second;

public class Service {
public static void print(String stringParam) {
try {
synchronized (stringParam) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second;

public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service = new Service();

        ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

出现这样的情况就是因为String的两个值都是AA,两个线程持有相同的锁,所以造成线程B不能执行。这就是String常量池所带来的问题。

因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他的,比如new object()实例化一个object对象,但它并不放入缓存中。

package Second;

public class Service {
public static void print(Object object) {
try {
synchronized (object) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second;

public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second;

public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second;

public class Run {

    public static void main(String[] args) {

        Service service = new Service();

        ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

交替打印是因为持有的锁不是同一个

同步synchronized方法无限等待与解决

同步方法容易造成死循环

package Second;

public class Service {
synchronized public void methodA() {
Object object1 = new Object(); System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end"); } synchronized public void methodB() {
Object object2 = new Object(); System.out.println("methodB begin");
System.out.println("methodB end"); }
}
package Second;

public class ThreadA extends Thread {

    private Service service;

    public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodA();
} }
package Second;

public class ThreadB extends Thread {

    private Service service;

    public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodB();
} }
package Second;

public class Run {

    public static void main(String[] args) {
Service service = new Service(); ThreadA athread = new ThreadA(service);
athread.start(); ThreadB bthread = new ThreadB(service);
bthread.start();
} }

线程B永远得不到运行的机会,锁死了

package Second;

public class Service {
public void methodA() {
Object object1 = new Object();
synchronized (object1) {
System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end");
}
} public void methodB() {
Object object2 = new Object();
synchronized (object2) {
System.out.println("methodB begin");
System.out.println("methodB end");
}
}
}

最新文章

  1. 高性能PHP框架thinkphp5.0.0 Beta发布-为API开发而设计
  2. 【前端】event.target 和 event.currentTarget 的区别
  3. duxcms SQL Injection In /admin/module/loginMod.class.php
  4. ios xib 中的 size class
  5. WPF 的datagrid 列名中没有显示下划线是怎么回事?
  6. sqlserver字段类型详解
  7. 聚类算法:K-means 算法(k均值算法)
  8. css3中的BFC,IFC,GFC和FFC(转载)
  9. 【原】手写一个promise
  10. 如何用Python网络爬虫爬取网易云音乐歌曲
  11. 有道云笔记MarkDown 插入图片
  12. Solr 05 - Solr Web管理界面的基本使用
  13. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
  14. [转]PHP时区/MySql时区/Linux时区
  15. CSS实现输入框宽度随内容自适应效果
  16. ZZW原创_imdpd导入时产生的错误
  17. HPUX and AIX SSH 互信
  18. springmvc接收数组类型参数
  19. MySQL数据库调优技巧
  20. MYSQL-重做系统恢复MYSQL过程

热门文章

  1. Gradle 介绍
  2. vscode webstrom 配置 eslint 使用 airbnb 规范
  3. about gnu bash shell
  4. Kubernetes TensorFlow 默认 特定 集群管理器
  5. 使用python实现二分法查找
  6. 爬虫-Selenium -抱错ElementNotVisibleException: Message: element not visible
  7. vue --- axios , vuex
  8. UVA - 11624 Fire! 【BFS】
  9. Linux内核--并发【转】
  10. 51Nod 1627 瞬间移动 —— 组合数学