- 11.将任意对象作为对象监视器
- 12.多线程的死锁
- 13.锁对象的改变
接上一篇文章——【对象及变量的并发访问(二)——synchronized同步语句块(2)】
网址为:https://blog.csdn.net/qq_44307209/article/details/125420587
同步方法容易造成死循环。这时就可以使用同步块来解决这样的问题。
创建项目twoStop,类Service.java的代码如下:
public class Service {
Object objectA = new Object();
public void methodA() {
synchronized (objectA) {
System.out.println(" methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println(" methodA end");
}
}
Object objectB = new Object();
public void methodB() {
synchronized (objectB) {
System.out.println(" methodB begin");
System.out.println(" methodB end");
}
}
}
创建线程类ThreadA.java代码如下:
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.methodA();
}
}
创建线程类ThreadB.java代码如下:
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.methodB();
}
}
创建运行类Run.java代码如下:
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();
}
}
运行结果如下所示:
methodA begin methodB begin methodB end
没有出现同步等待的情况
Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待根本不可能被释放的锁,从而导致所有的任务都无法继续完成。在多线程技术中,“死锁”是必须避免的,因为这会造成线程的“假死”。
创建名称dealLockTest的项目,DealThread.java类代码如下:
public class DealThread implements Runnable {
public String username;
public Object lock1 = new Object();
public Object lock2 = new Object();
public void setFlag(String username) {
this.username = username;
}
@Override
public void run() {
if (username.equals("a")) {
synchronized (lock1) {
try {
System.out.println("username = " + username);
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("按lock1->lock2代码顺序执行了");
}
}
}
if (username.equals("b")) {
synchronized (lock2) {
try {
System.out.println("username = " + username);
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("按lock2->lock1代码顺序执行了");
}
}
}
}
}
创建运行类Run.java代码如下:
public class Run {
public static void main(String[] args) {
try {
DealThread t1 = new DealThread();
t1.setFlag("a");
Thread thread1 = new Thread(t1);
thread1.start();
Thread.sleep(100);
t1.setFlag("b");
Thread thread2 = new Thread(t1);
thread2.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果如下所示:
username = a username = b
出现死锁
可以使用JDK自带的工具来监测是否有死锁的现象。首先进入CMD 工具,再进入JDK的安装文件夹中的bin目录,执行jps命令。得到运行线程Run的id值是20552,再执行jstack命令(命令:jstack -l 20552),查看结果。
死锁是程序设计的Bug,在设计程序时就要避免双方互相持有对方的锁的情况。需要说明的是,本实验使用synchronized嵌套的代码结构来实现死锁,其实不使用嵌套的synchronized 代码结构也会出现死锁,与嵌套不嵌套无任何的关系,不要被代码结构所误导。只要互相等待对方释放锁就有可能出现死锁。
在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,
则这些线程之间就是同步的;如果分别获得锁对象,这些线程直接就是异步的。
以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git



