可能出现的问题场景
- 文件创建冲突:多个线程同时尝试在同一目录下创建同名文件,可能导致部分线程创建失败,或者创建出不完整的文件。
- 文件删除问题:一个线程准备删除某个文件时,另一个线程可能正在读取或写入该文件,这可能导致数据丢失或读取错误。同时,多个线程尝试删除同一文件,可能出现重复删除或部分删除的情况。
- 目录遍历混乱:在遍历目录时,一个线程可能正在添加或删除目录项,而另一个线程正在遍历,这会导致遍历结果不准确或引发异常。
解决方案及代码示例
- 使用
synchronized
关键字
import java.io.File;
public class DirectoryManager {
private static final Object lock = new Object();
public static void createFile(String filePath) {
synchronized (lock) {
File file = new File(filePath);
try {
if (file.createNewFile()) {
System.out.println("File created: " + file.getName());
} else {
System.out.println("File already exists: " + file.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void deleteFile(String filePath) {
synchronized (lock) {
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println("File deleted: " + file.getName());
} else {
System.out.println("Failed to delete file: " + file.getName());
}
} else {
System.out.println("File does not exist: " + file.getName());
}
}
}
}
- 使用
ReentrantLock
import java.io.File;
import java.util.concurrent.locks.ReentrantLock;
public class DirectoryManagerWithReentrantLock {
private static final ReentrantLock lock = new ReentrantLock();
public static void createFile(String filePath) {
lock.lock();
try {
File file = new File(filePath);
if (file.createNewFile()) {
System.out.println("File created: " + file.getName());
} else {
System.out.println("File already exists: " + file.getName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void deleteFile(String filePath) {
lock.lock();
try {
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println("File deleted: " + file.getName());
} else {
System.out.println("Failed to delete file: " + file.getName());
}
} else {
System.out.println("File does not exist: " + file.getName());
}
} finally {
lock.unlock();
}
}
}
代码说明
synchronized
实现:
- 定义了一个静态的
Object
作为锁对象 lock
。
- 在
createFile
和 deleteFile
方法中,使用 synchronized
块包裹文件操作代码。这确保了同一时间只有一个线程能够执行这些文件操作,避免资源竞争。
ReentrantLock
实现:
- 创建了一个静态的
ReentrantLock
对象 lock
。
- 在
createFile
和 deleteFile
方法中,首先调用 lock.lock()
获取锁,确保只有一个线程能进入临界区执行文件操作。
- 使用
try - finally
块,在 finally
中调用 lock.unlock()
释放锁,保证无论操作是否成功,锁都会被释放,避免死锁。