java中的同步方法如何保证对象不受干扰

java中的同步方法如何保证对象不受干扰,java,multithreading,synchronized,Java,Multithreading,Synchronized,我想确保(我理解正确)并了解java中的同步方法如何保证不干扰对象 例如,我有以下代码: private void update_curr_mat(int stock_ind, double price, double time) { synchronized(current_mat_data) { current_mat_data[stock_ind][HIGH_PRICE_IND] = price; current_mat_data[stock

我想确保(我理解正确)并了解java中的同步方法如何保证不干扰对象

例如,我有以下代码:

private void update_curr_mat(int stock_ind, double price, double time)
{
    synchronized(current_mat_data)
    {
        current_mat_data[stock_ind][HIGH_PRICE_IND] = price;
        current_mat_data[stock_ind][LOW_PRICE_IND] = price;
        current_mat_data[stock_ind][CLOSE_IND] = price;
        current_mat_data[stock_ind][HIGHEST_IND] = price;
        current_mat_data[stock_ind][LOWEST_IND] = price;

        current_mat_data[stock_ind][CURR_TIME_IND] = time;
    }
}
在本例中,很明显,
current\u mat\u data
是同步的,当调用该方法时,另一个线程无法写入
current\u mat\u data
对象

在本例中:

private synchronized void update_curr_mat(int stock_ind, double price, double time)
{
        current_mat_data[stock_ind][HIGH_PRICE_IND] = price;
        current_mat_data[stock_ind][LOW_PRICE_IND] = price;
        current_mat_data[stock_ind][CLOSE_IND] = price;
        current_mat_data[stock_ind][HIGHEST_IND] = price;
        current_mat_data[stock_ind][LOWEST_IND] = price;

        current_mat_data[stock_ind][CURR_TIME_IND] = time;
}
同步是在方法定义中完成的。我知道它保证了两个线程不能同时调用这个方法


所以我的问题是,当第二个exmaple中的函数被调用时,它保证其他线程不能访问对象
当前的\u mat\u数据
?如果这是真的,你能解释一下它是如何工作的吗?如果我写的东西不对或不清楚,请告诉我。

据我所知,不,虽然其他线程可能无法调用update\u curr\u mat,但它仍然可以访问另一个非同步的方法来操作update\u curr\u mat对象。例如,如果您有其他方法:

public void mess_with_curr_mat(int stock_ind, double price)
{ 
    current_mat_data[stock_ind][HIGH_PRICE_IND] = price;
}

另一个线程可以调用这个方法,但是没有任何东西可以阻止它这样做,因为它是不同步的。但是,如果将update\u curr\u mat方法设置为静态,并且将当前的\u mat\u数据变量设置为静态,则可以避免此风险,因为这将在实际的类对象本身上进行同步。

据我所知,不是,虽然可能会阻止另一个线程调用update\u curr\u mat,但它仍然可以访问另一个线程,非同步的方法,用于操纵update\u curr\u mat对象。例如,如果您有其他方法:

public void mess_with_curr_mat(int stock_ind, double price)
{ 
    current_mat_data[stock_ind][HIGH_PRICE_IND] = price;
}
另一个线程可以调用这个方法,但是没有任何东西可以阻止它这样做,因为它是不同步的。但是,如果将update\u curr\u mat方法设置为静态,并且将当前的\u mat\u数据变量设置为静态,则可以避免此风险,因为这将在实际的类对象本身上同步

在本例中,很明显,当前的\u mat_数据是同步的,当调用该方法时,另一个线程无法写入当前的\u mat_数据对象

错。放置
synchronized(someObject)
不会阻止任何其他线程使用
someObject
执行操作

这里发生的唯一事情是,只有一个线程可以进入受保护的块!这是一种锁定代码段的方法。不是锁定该对象的方法

换句话说:假设update\u curr\u mat()是唯一更新该对象的方法-那么是的,这个
synchronized
语句确实有效地防止多个线程篡改
当前的\u mat\u dat

同样:您不能通过这种方式锁定对象。防止并行更改的唯一方法是确保修改该对象的每一行代码都由相同的锁保护

在本例中,很明显,当前的\u mat_数据是同步的,当调用该方法时,另一个线程无法写入当前的\u mat_数据对象

错。放置
synchronized(someObject)
不会阻止任何其他线程使用
someObject
执行操作

这里发生的唯一事情是,只有一个线程可以进入受保护的块!这是一种锁定代码段的方法。不是锁定该对象的方法

换句话说:假设update\u curr\u mat()是唯一更新该对象的方法-那么是的,这个
synchronized
语句确实有效地防止多个线程篡改
当前的\u mat\u dat

同样:您不能通过这种方式锁定对象。防止并行更改的唯一方法是确保修改该对象的每一行代码都由同一个锁保护。

在这两个示例中,没有绝对保证(仅给出您所展示的内容)任何东西都不能编辑该对象。就是这个声明

在本例中,很明显,当前的\u mat_数据是同步的,当调用该方法时,另一个线程无法写入当前的\u mat_数据对象

这是不正确的

唯一的保证是没有两个线程可以同时持有同一个锁;一个线程必须持有适当的锁才能执行同步块或方法(因此,如果另一个线程持有该锁,则该线程必须等到该锁可用后,才能获取该锁并进入该块或方法)

您必须使用封装和良好的编程来构建任何额外的保证

令人困惑的是,每个对象都可以用作锁,但编辑该对象时不必持有对象的锁。也就是说,Java不需要您拥有锁来编辑对象。要强制执行这样的规则,您需要以各种方式编辑对象,使其包含在将该对象用作锁的同步块或方法中

您的两个示例之间的区别只是将哪个对象用作锁。第一个示例使用
current_mat_data
引用的对象;第二个使用
this
引用的对象(调用
update\u cur\u mat
方法的对象实例)。(静态方法将使用类对象。)

在这两个示例中,没有任何东西可以编辑对象的绝对保证(仅给出您所展示的内容)。就是这个声明

在本例中,很明显,当前的\u mat_数据是同步的,当调用该方法时,另一个线程无法写入当前的\u mat_数据对象

这是不正确的

唯一的保证是没有两个线程可以同时持有同一个锁;那是一根线吗
final Object myLockA = new Object();
final Object myLockB = new Object();

void funcA() {
  synchronized(myLockA) { 
    // ... 
  }
}

void funcB() {
  synchronized(myLockB) { 
    // ... 
  }
}