多线程场景下仅访问同一同步方法时锁定线程的实现方案咨询
这个问题的核心在于你对静态synchronized方法的锁机制理解有点偏差——静态同步方法锁的是类的Class对象(比如你的类是ErrorLogger的话,锁就是ErrorLogger.class),所有静态同步方法共享这同一把锁。所以不管线程调用的是哪个静态同步方法,只要有一个线程占着锁,其他线程就得等,这就是你遇到的问题。
针对你的writeError方法,我给你两个最直接的可行方案:
方案1:使用专属的静态锁对象替换方法级synchronized
给writeError方法单独分配一个私有静态锁对象,这样只有调用这个方法的线程才会竞争这把锁,其他静态同步方法(如果有的话)可以用各自的锁,互相不干扰。代码示例:
// 定义专属的静态锁对象,private保证外部无法访问 private static final Object WRITE_ERROR_LOCK = new Object(); public static void writeError(Exception err) { // 仅在这个代码块内锁定专属锁 synchronized (WRITE_ERROR_LOCK) { String time = longDate(); try { FileWriter path = new FileWriter("ERROR - " + time + ".txt", true); err.printStackTrace(new PrintWriter(path)); path.flush(); } catch (IOException e) { // 建议不要空catch,至少打印日志方便排查问题 e.printStackTrace(); } } }
原理很简单:每个需要独立锁定的方法用自己的锁对象,不同方法的锁之间完全隔离,只有同一方法的并发调用才会触发等待。
方案2:使用ReentrantLock实现更灵活的锁定
如果你需要更灵活的锁控制(比如公平锁、可中断锁等),可以用java.util.concurrent.locks.ReentrantLock替代synchronized。代码示例:
import java.util.concurrent.locks.ReentrantLock; // 定义专属的ReentrantLock private static final ReentrantLock WRITE_ERROR_LOCK = new ReentrantLock(); public static void writeError(Exception err) { WRITE_ERROR_LOCK.lock(); // 获取锁 try { String time = longDate(); try { FileWriter path = new FileWriter("ERROR - " + time + ".txt", true); err.printStackTrace(new PrintWriter(path)); path.flush(); } catch (IOException e) { e.printStackTrace(); } } finally { WRITE_ERROR_LOCK.unlock(); // 必须在finally里释放锁,防止异常导致锁泄漏 } }
这个方案的优势是锁的操作更可控,比如你可以用tryLock()尝试获取锁而不是一直等待,不过对于你的需求来说,两种方案都能完美解决问题。
最后提个小提醒:你的longDate()方法虽然不是同步的,但要确保它本身是线程安全的——如果它内部有共享变量或者非线程安全的操作,可能会导致时间字符串出现异常,这一点也要注意哦。
内容的提问来源于stack exchange,提问作者KunLun
相关产品推荐
相关产品推荐

