为所有线程锁定对象?
Lock objects for all threads?
我有这个小代码示例,在修改列表时,我用同步锁定了它,但是在读取列表时它出现了 ConcurrentModificationException,因为没有 "synchronized" 锁无效。是否可以为所有使用对象的线程锁定对象,甚至是非同步线程?
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
final Random r = new Random(System.currentTimeMillis());
List<Integer> list = new ArrayList<>();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (list) {
list.add(r.nextInt());
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
for (Integer i : list) {
System.out.println(i);
}
}
}
}).start();
}
}
背景是我不想更改读取对象的代码中的所有部分
您可以考虑使用 List 的并发实现,而不是 ArrayList。也许是 CopyOnWriteArrayList。
final List<Integer> list = new CopyOnWriteArrayList<Integer>();
如果可以修改并发使用该对象的函数,只需在每个临界区添加synchronized
:
while (true) {
synchronized(list){
for (Integer i : list) {
System.out.println(i);
}
}
}
如果不能,请创建负责锁定线程的指定锁:
Lock lock = new Lock();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
如果其中一个函数已经进行了一些锁定,后者可能会减慢进程,但通过这种方式,您可以确保始终同步对并发对象的访问。
Is it possible to lock an object for all threads which use the object.
一句话,不能。当一个线程进入synchronized(foo) {...}
块时,不会阻止其他线程访问或修改foo
。它唯一阻止的是,它阻止其他线程同时在同一个对象上进行同步。
您 可以 做的是,您可以创建自己的 class 来封装锁和锁保护的数据。
class MyLockedList {
private final Object lock = new Object();
private final List<Integer> theList = new ArrayList<>();
void add(int i) {
synchronized(lock) {
theList.add(i);
}
}
void printAll() {
synchronized(lock) {
for (Integer i : theList) {
System.out.println(... i ...);
}
}
}
...
}
我有这个小代码示例,在修改列表时,我用同步锁定了它,但是在读取列表时它出现了 ConcurrentModificationException,因为没有 "synchronized" 锁无效。是否可以为所有使用对象的线程锁定对象,甚至是非同步线程?
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
final Random r = new Random(System.currentTimeMillis());
List<Integer> list = new ArrayList<>();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (list) {
list.add(r.nextInt());
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
for (Integer i : list) {
System.out.println(i);
}
}
}
}).start();
}
}
背景是我不想更改读取对象的代码中的所有部分
您可以考虑使用 List 的并发实现,而不是 ArrayList。也许是 CopyOnWriteArrayList。
final List<Integer> list = new CopyOnWriteArrayList<Integer>();
如果可以修改并发使用该对象的函数,只需在每个临界区添加synchronized
:
while (true) {
synchronized(list){
for (Integer i : list) {
System.out.println(i);
}
}
}
如果不能,请创建负责锁定线程的指定锁:
Lock lock = new Lock();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
如果其中一个函数已经进行了一些锁定,后者可能会减慢进程,但通过这种方式,您可以确保始终同步对并发对象的访问。
Is it possible to lock an object for all threads which use the object.
一句话,不能。当一个线程进入synchronized(foo) {...}
块时,不会阻止其他线程访问或修改foo
。它唯一阻止的是,它阻止其他线程同时在同一个对象上进行同步。
您 可以 做的是,您可以创建自己的 class 来封装锁和锁保护的数据。
class MyLockedList {
private final Object lock = new Object();
private final List<Integer> theList = new ArrayList<>();
void add(int i) {
synchronized(lock) {
theList.add(i);
}
}
void printAll() {
synchronized(lock) {
for (Integer i : theList) {
System.out.println(... i ...);
}
}
}
...
}