java避免死锁
我们的应用程序(使用java)非常复杂,我得到了下面的示例代码,这些代码将在多线程环境中使用 现在的问题是,当我运行下面的代码(作为独立的主代码运行)时,我遇到了死锁 位置类别:-java避免死锁,java,multithreading,Java,Multithreading,我们的应用程序(使用java)非常复杂,我得到了下面的示例代码,这些代码将在多线程环境中使用 现在的问题是,当我运行下面的代码(作为独立的主代码运行)时,我遇到了死锁 位置类别:- public class Location implements Runnable { private final int id; private final int[] dependentLocationIds; private final Lock lock = new Reentr
public class Location implements Runnable {
private final int id;
private final int[] dependentLocationIds;
private final Lock lock = new ReentrantLock();
public Location(int id, int[] dependentLocationIds) {
this.id = id;
this.dependentLocationIds = dependentLocationIds;
}
public int getId() {
return id;
}
public boolean blockLocation() {
lock.lock();
return true;
}
public boolean releaseLocation() {
lock.unlock();
return true;
}
public boolean occupy() {
boolean occupationStatus = false;
//order ids first
Arrays.sort(dependentLocationIds);
lock.lock();
try {
//below sleep temporarily added to track the progress slowly
Thread.sleep(1000);
//Check dependentLocations are NOT being modified concurrently
for(int id : dependentLocationIds) {
Location location = LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+": blocking required dependent location :"+id);
location.blockLocation();
}
//the above blocked Locations will be released in leave()
//complex business logic to check and then make occupationStatus to true
occupationStatus = true;
System.out.println(id + ": location occupied by:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(!occupationStatus) {
lock.unlock();
}
//if occupationStatus is true, the lock will be released in leave()
}
return occupationStatus;
}
public boolean leave() {
boolean leaveStatus = false;
//order ids first
Arrays.sort(dependentLocationIds);
try {
//below sleep temporarily added to track the progress slowly
Thread.sleep(1000);
//complex business logic to check and then make leaveStatus to true
leaveStatus = true;
//now release dependent locations in reverse order
for(int i=dependentLocationIds.length; i>0;i--) {
Location location = LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+": releasing required dependent location :"+id);
location.releaseLocation();
}
System.out.println(id + ": location released by "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return leaveStatus;
}
public void run() {
occupy();
//some business logic goes here
leave();
}
public static void main(String[] args) {
List<Location> locations = LocationHelper.getLocations();
for(Location location : locations) {
//Each location runs in different threads here
new Thread(location, "THREAD-"+location.getId()).start();
}
}
}
public class LocationHelper {
private static final List<Location> locations = new ArrayList<>();
static {
int[] locationids1 = {2, 3, 4, 5};
Location location1 = new Location(1, locationids1);
locations.add(location1);
int[] locationids2 = {1, 3, 4};
Location location2 = new Location(2, locationids2);
locations.add(location2);
int[] locationids3 = {1, 2, 4};
Location location3 = new Location(3, locationids3);
locations.add(location3);
int[] locationids4 = {3, 5};
Location location4 = new Location(4, locationids4);
locations.add(location4);
int[] locationids5 = {1, 2, 3, 4};
Location location5 = new Location(5, locationids5);
locations.add(location5);
}
public static List<Location> getLocations() {
return locations;
}
public static Location getLocation(int id) {
Location required = null;
for(Location location : locations) {
if(location.getId() == id) {
required = location;
}
}
return required;
}
}
公共类位置实现可运行{
私有最终int id;
私有final int[]dependentLocationId;
private final Lock=new ReentrantLock();
公共位置(int id,int[]DependentLocationId){
this.id=id;
this.DependentLocationId=DependentLocationId;
}
公共int getId(){
返回id;
}
公共布尔块位置(){
lock.lock();
返回true;
}
公共布尔releaseLocation(){
lock.unlock();
返回true;
}
公共布尔占用(){
布尔职业状态=false;
//先订购ID
Arrays.sort(dependentLocationId);
lock.lock();
试一试{
//下面临时添加睡眠以缓慢跟踪进度
睡眠(1000);
//没有同时修改Check DEpendentLocation
for(int-id:DependentLocationId){
Location Location=LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+”:阻止所需的依赖位置:“+id”);
location.blockLocation();
}
//上述被阻止的位置将在leave()中释放
//检查复杂的业务逻辑,然后将occupationStatus设置为true
职业状态=真;
System.out.println(id+):被“+Thread.currentThread().getName()”占用的位置;
}捕捉(中断异常e){
e、 printStackTrace();
}最后{
如果(!职业状态){
lock.unlock();
}
//如果occupationStatus为true,将在leave()中释放锁
}
返回职业状态;
}
公共布尔休假(){
布尔状态=假;
//先订购ID
Arrays.sort(dependentLocationId);
试一试{
//下面临时添加睡眠以缓慢跟踪进度
睡眠(1000);
//检查复杂的业务逻辑,然后将leaveStatus设置为true
levestatus=true;
//现在按相反顺序释放依赖位置
对于(int i=DependentLocationId.length;i>0;i--){
Location Location=LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+”:释放所需的依赖位置:“+id”);
location.releaseLocation();
}
System.out.println(id+):由“+Thread.currentThread().getName()”释放的位置;
}捕捉(中断异常e){
e、 printStackTrace();
}最后{
lock.unlock();
}
返回状态;
}
公开募捐{
占领();
//这里有一些商业逻辑
离开();
}
公共静态void main(字符串[]args){
List locations=LocationHelper.getLocations();
对于(位置:位置){
//每个位置在这里的不同线程中运行
新线程(位置,“Thread-”+location.getId()).start();
}
}
}
LocationHelper类:-
public class Location implements Runnable {
private final int id;
private final int[] dependentLocationIds;
private final Lock lock = new ReentrantLock();
public Location(int id, int[] dependentLocationIds) {
this.id = id;
this.dependentLocationIds = dependentLocationIds;
}
public int getId() {
return id;
}
public boolean blockLocation() {
lock.lock();
return true;
}
public boolean releaseLocation() {
lock.unlock();
return true;
}
public boolean occupy() {
boolean occupationStatus = false;
//order ids first
Arrays.sort(dependentLocationIds);
lock.lock();
try {
//below sleep temporarily added to track the progress slowly
Thread.sleep(1000);
//Check dependentLocations are NOT being modified concurrently
for(int id : dependentLocationIds) {
Location location = LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+": blocking required dependent location :"+id);
location.blockLocation();
}
//the above blocked Locations will be released in leave()
//complex business logic to check and then make occupationStatus to true
occupationStatus = true;
System.out.println(id + ": location occupied by:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(!occupationStatus) {
lock.unlock();
}
//if occupationStatus is true, the lock will be released in leave()
}
return occupationStatus;
}
public boolean leave() {
boolean leaveStatus = false;
//order ids first
Arrays.sort(dependentLocationIds);
try {
//below sleep temporarily added to track the progress slowly
Thread.sleep(1000);
//complex business logic to check and then make leaveStatus to true
leaveStatus = true;
//now release dependent locations in reverse order
for(int i=dependentLocationIds.length; i>0;i--) {
Location location = LocationHelper.getLocation(id);
System.out.println(Thread.currentThread().getName()+": releasing required dependent location :"+id);
location.releaseLocation();
}
System.out.println(id + ": location released by "+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return leaveStatus;
}
public void run() {
occupy();
//some business logic goes here
leave();
}
public static void main(String[] args) {
List<Location> locations = LocationHelper.getLocations();
for(Location location : locations) {
//Each location runs in different threads here
new Thread(location, "THREAD-"+location.getId()).start();
}
}
}
public class LocationHelper {
private static final List<Location> locations = new ArrayList<>();
static {
int[] locationids1 = {2, 3, 4, 5};
Location location1 = new Location(1, locationids1);
locations.add(location1);
int[] locationids2 = {1, 3, 4};
Location location2 = new Location(2, locationids2);
locations.add(location2);
int[] locationids3 = {1, 2, 4};
Location location3 = new Location(3, locationids3);
locations.add(location3);
int[] locationids4 = {3, 5};
Location location4 = new Location(4, locationids4);
locations.add(location4);
int[] locationids5 = {1, 2, 3, 4};
Location location5 = new Location(5, locationids5);
locations.add(location5);
}
public static List<Location> getLocations() {
return locations;
}
public static Location getLocation(int id) {
Location required = null;
for(Location location : locations) {
if(location.getId() == id) {
required = location;
}
}
return required;
}
}
公共类LocationHelper{
私有静态最终列表位置=新ArrayList();
静止的{
int[]locationids1={2,3,4,5};
位置location1=新位置(1,位置IDS1);
位置。添加(位置1);
int[]locationids2={1,3,4};
位置location2=新位置(2,位置ids2);
位置。添加(位置2);
int[]locationids3={1,2,4};
位置location3=新位置(3,位置IDS3);
位置。添加(位置3);
int[]locationids4={3,5};
位置location4=新位置(4,位置IDS4);
位置。添加(位置4);
int[]locationids5={1,2,3,4};
位置location5=新位置(5,位置IDS5);
位置。添加(位置5);
}
公共静态列表getLocations(){
返回地点;
}
公共静态位置getLocation(int-id){
所需位置=空;
对于(位置:位置){
if(location.getId()==id){
所需=位置;
}
}
要求归还;
}
}
核心要求是当我更新特定的“位置”时
对象,不应允许任何依赖的“位置”对象
改变因此,我也尝试锁定依赖对象,这就是复杂性产生的原因
我尝试根据“位置id”(唯一)对位置对象进行排序,然后锁定位置对象,以避免死锁,但没有运气。
你能帮我修改一下代码以避免死锁吗
如何重构“Location”类以消除上述复杂性?
或者,“Location”类还有其他更好的设计选项(使用并发api)来简化上述逻辑吗?请帮助。订购的想法看起来不错,订购必须解决解除死锁问题。如果你总是以同样的顺序获得锁,你就会安全 然而,我注意到您只订购直系亲属。在开始锁定之前,您应该递归地对所有依赖项进行排序。并且自己的实例也应该将自己放入要排序的列表中 这样,您将安全地锁定每个位置的所有“依赖关系树” 如需说明,请仅查看以下示例
public boolean occupy() {
boolean occupationStatus = false;
masterLock.lock();
try{
//order ids first
Arrays.sort(dependentLocationIds);
if(lock.tryLock()){
//handle already blocked
}
try {
//bunch of stuff
} finally {
if(!occupationStatus) {
lock.unlock();
}
}
}finally{
masterLock.unlock();
}
return occupationStatus;
}
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Location
implements Runnable
{
private final int id;
private final List<Integer> dependentLocationIds;
private final Lock lock = new ReentrantLock();
private boolean isUnlocked = true;
public Location(int id, List<Integer> dependentLocationIds)
{
this.id = id;
this.dependentLocationIds = dependentLocationIds;
Collections.sort(dependentLocationIds);
}
public int getId()
{
return id;
}
public List<Integer> getDependentLocationIds()
{
return dependentLocationIds;
}
public boolean isUnlocked()
{
return isUnlocked;
}
public boolean blockLocation()
{
lock.lock();
isUnlocked = false;
System.out.printf("Location: %d occupied by: %s\n", this.getId(),
Thread.currentThread().getName());
return isUnlocked;
}
public boolean releaseLocation()
{
lock.unlock();
isUnlocked = true;
System.out.printf("Location: %d released by: %s\n", this.getId(),
Thread.currentThread().getName());
return isUnlocked;
}
public void occupy()
{
while (!LocationHelper.acquireLocks(this))
{
try
{
System.out.printf("Location: %d sleeping during occupy on: %s\n",
this.getId(), Thread.currentThread().getName());
Thread.sleep(1500);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
// below sleep added to track the progress slowly
Thread.sleep(1000);
System.out.printf("Location: %d doing something on: %s\n", this.getId(),
Thread.currentThread().getName());
}
catch (InterruptedException e)
{
e.printStackTrace();
LocationHelper.releaseLocks(this);
}
}
public void leave()
{
try
{
// below sleep added to track the progress slowly
Thread.sleep(1000);
System.out.printf("Location: %d is attempting to leave on: %s\n",
this.getId(), Thread.currentThread().getName());
LocationHelper.releaseLocks(this);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
LocationHelper.releaseLocks(this);
}
}
public void run()
{
occupy();
leave();
}
public static void main(String[] args)
{
List<Location> locations = LocationHelper.getLocations();
for (Location location : locations)
{
// Each location runs in different threads here
new Thread(location, "THREAD-" + location.getId()).start();
}
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class LocationHelper
{
private static List<Location> holdsLocks = new ArrayList<Location>();
private static final List<Location> locations = new ArrayList<>();
private static int printLocks = 0;
static
{
locations.add(new Location(1, Arrays.asList(1, 2, 3, 4, 5)));
locations.add(new Location(2, Arrays.asList(1, 2, 3, 4)));
locations.add(new Location(3, Arrays.asList(1, 2, 3, 4)));
locations.add(new Location(4, Arrays.asList(3, 4, 5)));
locations.add(new Location(5, Arrays.asList(1, 2, 3, 4, 5)));
}
public static List<Location> getLocations()
{
return locations;
}
public static Location getLocation(int id)
{
return locations.stream().filter(l -> l.getId() == id).findFirst()
.orElse(null);
}
public static synchronized boolean acquireLocks(Location location)
{
if (printLocks % 5 == 0)
{
locations.stream()
.forEach(l -> System.out.printf("Location: %d status: %s\n",
l.getId(), String.valueOf(l.isUnlocked())));
}
List<Location> required = location.getDependentLocationIds().stream()
.map(LocationHelper::getLocation).collect(Collectors.toList());
// If not available fail to lock.
if (required.stream().filter(l -> !l.isUnlocked()).count() > 0L)
{
return false;
}
else
{
try
{
required.stream().forEach(Location::blockLocation);
holdsLocks.add(location);
return true;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
required.stream().forEach(Location::releaseLocation);
return false;
}
}
}
public static boolean releaseLocks(Location location)
{
if (!holdsLocks.contains(location))
{
return false;
}
else
{
List<Location> required = location.getDependentLocationIds().stream()
.map(LocationHelper::getLocation).collect(Collectors.toList());
try
{
required.stream().forEach(Location::releaseLocation);
holdsLocks.remove(location);
return true;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
}
}