Java 在多个对象上同步
在前面的问题->中,我收到了一个很好的解决方案,可以解决我的问题。 但我还不明白到底是怎么回事 因此,如果我有许多线程可以同时进入这个同步块,根据java文档,这段代码是:Java 在多个对象上同步,java,multithreading,Java,Multithreading,在前面的问题->中,我收到了一个很好的解决方案,可以解决我的问题。 但我还不明白到底是怎么回事 因此,如果我有许多线程可以同时进入这个同步块,根据java文档,这段代码是: synchronized(...){ //atomic for the operation inside } 所以,我在问: 此操作是原子操作的原因: for (int j = 0; j < column; j++) { matrix[row][j] += 1;
synchronized(...){
//atomic for the operation inside
}
所以,我在问:
此操作是原子操作的原因:
for (int j = 0; j < column; j++) {
matrix[row][j] += 1;
}
而不是这个:
System.out.println("begin print");
for (int i = 0; i < this.row; i++) {
System.out.println();
for (int j = 0; j < column; j++)
System.out.print(matrix[i][j]);
}
System.out.println();
System.out.println("end print");
我的全部职能是:
public void increaseRow(Integer row) {
synchronized (rows.get(row)) {
for (int j = 0; j < column; j++) {
matrix[row][j] += 1;
}
System.out.println("begin print");
for (int i = 0; i < this.row; i++) {
System.out.println();
for (int j = 0; j < column; j++)
System.out.print(matrix[i][j]);
}
System.out.println();
System.out.println("end print");
}
}
如果有人能给我一个有用的解释,我将不胜感激。为什么不使用类对象:synchronizedthis 或者,更安全的是:synchronizedYourClassName.class 还是别的锁
Object lock = new Object();
...
public void someMethod(){
synchronized(lock){...}
}
创建的每个Java对象,包括加载的每个类,都有一个关联的锁或监视器。将代码放在同步块中会使编译器在执行代码之前附加指令以获取指定对象上的锁,然后由于代码正常或异常完成而将其释放。在获取锁和释放锁之间,线程被称为拥有锁。在线程A想要获得锁的时候,如果线程B已经拥有它,那么线程A必须等待线程B释放它。
但是,如果您的锁发生更改,而线程在同步块中使用此锁,则可能会发生另一个块可以使用此更改的锁进入同步块的情况。
例如:
时间线:
线程1:
调用printValue//获取锁
线程2:
锁定=新对象//锁变了,现在是另一个对象
正在调用增量//获取此新锁。旧锁仍由thread1保留
值正在递增。
威胁1:
打印错误的值
编辑:没有看到他需要为每一行设置锁。正如注释中所述,System.out.println不是线程安全操作 问题在于锁定关键部分的方式
synchronized (rows.get(row)) { }
这段代码意味着,您锁定的是特定的行,而不是整个表,因此,如果您有N行,这意味着同时存在N个锁,因此N个线程可以并行地同时运行填充System.out
锁定一行可以提供更好的并行性:处理第2行的线程可以与处理第3行的线程同时工作
另一种选择是对整个表部分使用一个锁
Object lock = new Object();
...
public void someMethod(){
synchronized(lock){...}
}
在这种情况下,只有一个锁,并且只有一个线程同时执行它,因此您可以有效地从代码中同步调用System.out
在表上锁定会降低并行性,因为您减少了可用的锁数:处理第2行的线程需要等待处理第3行的线程释放锁
线程安全,即同步保证只影响写在块中的函数,而不影响外部调用的函数,它不会使System.out原子操作。我想您会发现它是原子的,但打印假脱机不是。如果你有一些全局递增计数器,我想你会发现它们是有序的。传统上,打印速度很慢,而且是由多个线程写入的-在原子中制作不是一个好主意,我认为本质上,块内的递增部分也会很慢,为什么会同步?它不是原子的。这是相互排斥的。这是两件不同的事情,没有线程可以通过同步块,除非它不持有监视器本身。在这种情况下,监视器是hashmap中的对象。因此,它被排除在监视器之外。原子意味着作为一个单独的操作,虽然它可能被视为一个操作,但很明显,每个操作都可能影响上下文之外的其他对象中的状态。好的,我理解你所说的,但是如果T1和T2以两个不同的行进入这个块进行计算,打印也会同步。实际上,将更改函数的含义:虽然,这很可能是所需的。每个线程可以使用不同的行输入,因此阻止eNet对象监视器不是解决方案-1,但我不能投反对票。看我的答案,我想我在这里不清楚。如果您只需要锁定一行,保持单锁将降低性能和并行性。您要同步的是什么。打印输出或行的处理。如果确实要查看打印输出,则需要一个锁。。这不是表/行锁定辩论,这是printaccess辩论。啊,我明白了。好的,只要没有改变行的操作,这个锁就应该是好的。+1用于system.out解释。但我需要保持并行工作,因此我无法实例化全局锁。这意味着,您必须处理System.out污染,这是正常情况:
Object lock = new Object();
...
public void someMethod(){
synchronized(lock){...}
}