Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的同步-正确使用_Java_Multithreading_Synchronized - Fatal编程技术网

java中的同步-正确使用

java中的同步-正确使用,java,multithreading,synchronized,Java,Multithreading,Synchronized,我正在构建一个用于多进程线程的简单程序 我的问题更需要理解——当我必须使用保留字时 我需要在任何影响骨骼变量的方法中使用这个词吗 我知道我可以把它放在任何非静态的方法上,但我想了解更多 谢谢大家! 代码如下: public class Container { // *** data members *** public static final int INIT_SIZE=10; // the first (init) size of the set. public static final

我正在构建一个用于多进程线程的简单程序

我的问题更需要理解——当我必须使用保留字时

我需要在任何影响骨骼变量的方法中使用这个词吗

我知道我可以把它放在任何非静态的方法上,但我想了解更多

谢谢大家!

代码如下:

public class Container {
// *** data members ***
public static final int INIT_SIZE=10;  // the first (init) size of the set.
public static final int RESCALE=10;   // the re-scale factor of this set.
private int _sp=0;
public Object[] _data;
/************ Constructors ************/
public Container(){
    _sp=0;
    _data = new Object[INIT_SIZE];
}
public Container(Container other) {  // copy constructor
    this();
    for(int i=0;i<other.size();i++) this.add(other.at(i));
}

/** return true is this collection is empty, else return false. */
public synchronized boolean isEmpty() {return _sp==0;}

/** add an Object to this set */
public synchronized void add (Object p){
    if (_sp==_data.length) rescale(RESCALE);
    _data[_sp] = p;  // shellow copy semantic.
    _sp++;
}   

/** returns the actual amount of Objects contained in this collection */
public synchronized int size() {return _sp;}

/** returns true if this container contains an element which is equals to ob */
public synchronized boolean isMember(Object ob) {
    return get(ob)!=-1;
}

/** return the index of the first object which equals ob, if none returns -1 */
public synchronized int get(Object ob) {
    int ans=-1;
    for(int i=0;i<size();i=i+1)
        if(at(i).equals(ob)) return i;
    return ans;
}

/** returns the element located at the ind place in this container (null if out of range) */
public synchronized Object at(int p){
    if (p>=0 && p<size()) return _data[p];
    else return null;
}

我给你的建议是先读一读

几点意见:

同步所有方法会导致瓶颈 将_数据变量公开是一种不好的做法,并且会给并发编程带来困难。 似乎您正在重新实现一个集合,以便更好地使用现有集合。 变量名最好不要以_ 避免向代码中添加注释,并尝试使用声明性方法名称。
您可以查看以下有关同步方法的文档:

通过添加synchronized关键字,可以保证发生两件事:

首先,同一对象上的两个同步方法调用不可能交错。当一个线程正在为一个对象执行同步方法时,为同一对象块调用同步方法的所有其他线程将暂停执行,直到第一个线程处理完该对象为止

其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立“发生在之前”关系。这保证了对象状态的更改对所有线程都可见


因此,每当您需要保证一次只有一个线程访问您的变量来读/写它以避免一致性问题时,一种方法就是使您的方法同步。

使多线程访问的类安全是一个复杂的主题。如果你不是为了学习线程,你应该试着找到一个库来为你做这件事


话虽如此,一个开始是想象两个独立的线程以交替的方式逐行执行一个方法,看看会出什么问题。例如,如上所述的add方法易受数据破坏的影响。想象一下thread1和thread2同时调用add或多或少。如果thread1运行第2行,并且在到达第3行之前,thread2运行第2行,则thread2将覆盖thread1的值。因此,您需要某种方法来防止线程像那样交错。另一方面,isEmpty方法不需要同步,因为只有一条指令将值与0进行比较。同样,很难正确处理这些内容。

您需要保护构成对象状态的变量。如果在静态方法中使用这些变量,您也必须保护它们。但是,请注意,以下示例是错误的:

private static int stateVariable = 0;
//wrong!!!!
public static synchronized void increment() {
  stateVariable++;
}

public synchronized int getValue() {
  return stateVariable;
}
看起来上面的方法是安全的,但是这些方法在不同的锁上运行。以上内容大致对应于以下内容:

private static int stateVariable = 0;
//wrong!!!!
public static void increment() {
  synchronized (YourClassName.class) {
    stateVariable++;
  }
}

public synchronized int getValue() {
  synchronized (this) {
    return stateVariable;
  }
}

请注意,在混合使用静态方法和对象方法时,会使用不同的锁。

+1对于所有说要阅读教程的人,这里有一个总结

当一个线程可能创建其他线程不允许看到的临时情况时,您需要互斥,即同步块。假设在搜索树中存储了对象。向树中添加新对象的方法可能必须重新分配多个对象引用,并且在完成其工作之前,树将处于无效状态。如果允许一个线程在add方法中搜索树,而另一个线程在add方法中,则搜索函数可能返回错误的结果,或者更糟的是,可能导致程序崩溃

一种解决方案是同步add方法、search方法以及依赖于树结构的任何其他方法。所有这些都必须在同一个对象上同步。树的根节点是一个明显的选择

Java保证在任何给定时间同一对象上同步的线程不超过一个。因此,最多只有一个线程能够同时查看或更改树的内部结构,并且在add方法中创建的临时无效状态将是无害的


我上面的例子解释了互斥的原理,但它是保护搜索树的一个简单而低效的解决方案。更实用的方法是使用读写器锁,只在树的有趣部分而不是整个树上进行同步。复杂数据结构的实际同步是一个困难的问题,只要可能,您应该让其他人为您解决它。例如,如果您使用java.util.concurrent中的容器类而不是创建自己的数据结构,您可能会节省大量的工作和调试。

我很确定您也可以将同步的方法放在静态方法上…@user3580294是的,我知道,但我不需要同步静态方法。。
。如果您想了解更多信息,请阅读教程并测试代码。@LuiggiMendoza我是这个网站的新手,在哪里可以找到关于它的教程?注意:我写的代码,我的问题是关于多个进程这个网站是为特定的编程问题。这个问题不是很具体,答案可以在教程和中长期解释中找到。另外,如果您想要/需要一个支持添加多个对象并在并发中使用的类,请使用java.util.concurrent包中的并发集合。通常,您使用LinkedBlockingQueue实现的BlockingQueue。。。在加载备份阵列的大小和执行实际比较之间,可能会有另一个阵列清除该阵列thread@user3580294或者更好:不要重新发明轮子,使用支持java.util.concurrent包并发性的真实集合。@user3580294我担心。。。你认为任何影响骨骼变量的方法都需要同步吗?我明白你关于isEmpty的观点,但我认为不同步的行为同样好。在任何一种情况下,您得到的答案都反映了数组在接近调用时的某个时间点的状态。如果你想让这个答案仍然是正确的,你就必须同步更多围绕它的代码。我相信我们都在强调这一点,这是很难正确的