[英]Lock threads only if access same method of the same object
我有一个具有多线程项目通用方法的对象。 一些方法是同步的。 我的问题是,当一个线程访问同步方法而另一个线程访问另一个同步方法时。 这将使其中一个线程等待另一个线程。 我只想在访问相同的同步方法时锁定线程,但是我不知道如何。 我发现最近关键字已同步。
这是我的方法之一。
public synchronized static void writeError(Exception err){
String time = longDate();//here will get personalized current date
//longDate is not synchronized.
try {
FileWriter path = new FileWriter("ERROR - " + time + ".txt",true);
err.printStackTrace(new PrintWriter(path));
path.flush();
} catch (IOException e) {}
}
对这种方法有什么想法吗?
因此, synchronized
始终需要对象进行操作。 共享同一对象的所有synchronized
块都是互斥的 (即,一次只能有一个线程进入该块)。 将synchronized
放在方法声明中是简便的方法,例如,实例方法等于synchronized(this)
而静态方法等于synchronized(Foo.class)
(其中Foo
是包含静态方法的类)。
知道了这一点,您可以轻松地创建多个要同步的对象,控制哪些方法可以同时运行,哪些方法不能同时运行。
允许方法3与方法1或方法2同时运行的示例类,但方法1和方法2是互斥的。 另外,一次只能有一个线程运行每种方法。
public class Foo {
private final static Object lock1 = new Object();
private final static Object lock2 = new Object();
public static void method1() {
synchronized(lock1) {
...
}
}
public static void method2() {
synchronized(lock1) {
...
}
}
public static void method3() {
synchronized(lock2) {
...
}
}
}
也要注意静态与非静态。 这里的方法是静态的,锁是静态的,所以一切都很好。 如果方法是非静态的,则也将阻止在其他对象上调用方法,这可能不是您想要的。 在这种情况下,将锁设为非静态将使每个Foo
实例如前所述工作,但对于foo1.method1()
和foo2.method2()
而言,不会进行锁定,因为它们不会在同一对象。
正如Shubham Kadlag的答案所表明的, synchronized
并不是Java唯一的并发工具。 java.util.concurrent.locks
包具有用于锁定的类(而synchronized
是一种内置机制)。 例如, ReentrantReadWriteLock
允许您处理多个线程可以同时执行某项操作(读取),但是一次只允许一个线程进行修改操作(写入)的情况。 它们还允许您给锁定超时,而synchronized
将快乐地永远等待(不是通常需要tryLock()
,因为如果遇到死锁,这是编程错误)。
然后,您意识到手动锁定无论如何都是块,然后发现java.util.concurrent
有许多类可以将锁定隐藏起来,并提供各种高级功能。
正如Kamayan所提到的,对象上的同步将满足您的需求。
此外,如果您遇到性能问题或线程数量很多,则可以申请锁。
请参阅https://dzone.com/articles/synchronized-vs-lock
如以上文章所述,对于访问锁的少量线程(<4),同步是最好的选择;对于访问相同锁的大量线程,锁可能是最好的选择。
您可以参考http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/了解不同的锁示例。
为如下所示的所有方法创建一个单独的锁。
private static ReentrantLock writeErrorlock = new ReentrantLock();
public static void writeError(Exception err){
writeErrorlock.lock();
String time = longDate();//here will get personalized current date
//longDate is not synchronized.
try {
FileWriter path = new FileWriter("ERROR - " + time + ".txt",true);
err.printStackTrace(new PrintWriter(path));
path.flush();
} catch (IOException e) {
}
finally {
writeErrorlock.unlock();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.