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的观点,但我认为不同步的行为同样好。在任何一种情况下,您得到的答案都反映了数组在接近调用时的某个时间点的状态。如果你想让这个答案仍然是正确的,你就必须同步更多围绕它的代码。我相信我们都在强调这一点,这是很难正确的