当前位置:  开发笔记 > 编程语言 > 正文

java线程同步失败

如何解决《java线程同步失败》经验,为你挑选了1个好方法。

使用线程同步,Java似乎不是100%准确.此示例中的代码打印一个静态整数的值,该值由每个线程递增.如果输出包含相同的数字,uniq将多次识别它.每个示例都由Makefile脚本运行,以帮助说明问题.每个示例使用不同的同步/锁定方法,但似乎没有一个方法在100%的时间内都能正常工作.大多数复制发生在循环的早期,至少在这个系统上.

Makefile文件:

JAVA=/usr/local/jdk/bin/java
JAVAC=$(JAVA)c

build:
    $(JAVAC) Synchron.java
    $(JAVAC) SynchronVolatile.java
    $(JAVAC) SynchronFinal.java
    $(JAVAC) SynchronThis.java
    $(JAVAC) SynchronA.java
    $(JAVAC) SynchronObj.java

run:
    $(JAVA) Synchron | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
    $(JAVA) SynchronVolatile | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
    $(JAVA) SynchronFinal | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
    $(JAVA) SynchronThis | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
    $(JAVA) SynchronA | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true
    $(JAVA) SynchronObj | sort | uniq -c | egrep -v '^\s+1\s+' ; /bin/true

Synchron.java:

import java.io.*;
import java.util.*;

public class Synchron implements Runnable {
        static int a;

        synchronized public void adder() {
        Synchron.a++;
        System.out.println( Synchron.a );
        }

        public void run() {
                while( Synchron.a < 65535 ) {
                        adder();
                }
        }
        public static void main( String []args ) {
                ArrayList al = new ArrayList();

                try {
                        int i;
                        for( i = 0; i<10 ; i++ ) {
                                Synchron s = new Synchron();
                                Thread t = new Thread( s );
                                al.add(t);
                                t.start();
                        }

                        for( Thread t : al ) {
                                t.join();
                        }
                }
                catch( Exception e ) {
                        e.printStackTrace();
                }

        }
}

SynchronVolatile.java:

import java.io.*;
import java.util.*;

public class SynchronVolatile implements Runnable {
        static int a;
    static volatile Object o = new Object();

        public void adder() {
        synchronized( SynchronVolatile.o ) {
            SynchronVolatile.a++;
        }
        System.out.println( SynchronVolatile.a );
        }

        public void run() {
                while( SynchronVolatile.a < 65535 ) {
                        adder();
                }
        }
        public static void main( String []args ) {
                ArrayList al = new ArrayList();

                try {
                        int i;
                        for( i = 0; i<10 ; i++ ) {
                                SynchronVolatile s = new SynchronVolatile();
                                Thread t = new Thread( s );
                                al.add(t);
                                t.start();
                        }

                        for( Thread t : al ) {
                                t.join();
                        }
                }
                catch( Exception e ) {
                        e.printStackTrace();
                }

        }
}

SynchronFinal:这与SynchronVolatile.java相同,除了它使用Object o的final,而不是volatile.

SynchronThis.java:

import java.io.*;
import java.util.*;

public class SynchronThis implements Runnable {
        static int a;
    static volatile Object o = new Object();

        public void adder() {
        synchronized( this ) {
            SynchronThis.a++;
        }
        System.out.println( SynchronThis.a );
        }

        public void run() {
                while( SynchronThis.a < 65535 ) {
                        adder();
                }
        }
        public static void main( String []args ) {
                ArrayList al = new ArrayList();

                try {
                        int i;
                        for( i = 0; i<10 ; i++ ) {
                                SynchronThis s = new SynchronThis();
                                Thread t = new Thread( s );
                                al.add(t);
                                t.start();
                        }

                        for( Thread t : al ) {
                                t.join();
                        }
                }
                catch( Exception e ) {
                        e.printStackTrace();
                }

        }
}

SynchronA.java:

import java.io.*;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SynchronA implements Runnable {
        static int a;
    private volatile Lock lock = new ReentrantLock();

        public void adder() {
        lock.lock();
        SynchronA.a++;
        System.out.println( SynchronA.a );
        lock.unlock();
        }

        public void run() {
                while( SynchronA.a < 65535 ) {
                        adder();
                }
        }
        public static void main( String []args ) {
                ArrayList al = new ArrayList();

                try {
                        int i;
                        for( i = 0; i<10 ; i++ ) {
                                SynchronA s = new SynchronA();
                                Thread t = new Thread( s );
                                al.add(t);
                                t.start();
                        }

                        for( Thread t : al ) {
                                t.join();
                        }
                }
                catch( Exception e ) {
                        e.printStackTrace();
                }

        }
}

SynchronObj.java:

import java.io.*;
import java.util.*;

public class SynchronObj implements Runnable {
        static int a;
    Object o;

    public SynchronObj( Object obj ) {
        o = obj;
    }

        public void adder() {
        synchronized( o ) {
            SynchronObj.a++;
        }
        System.out.println( SynchronObj.a );
        }

        public void run() {
                while( SynchronObj.a < 65535 ) {
                        adder();
                }
        }
        public static void main( String []args ) {
                ArrayList al = new ArrayList();

        final Object o = new Object();

                try {
                        int i;
                        for( i = 0; i<10 ; i++ ) {
                                SynchronObj s = new SynchronObj( o );
                                Thread t = new Thread( s );
                                al.add(t);
                                t.start();
                        }

                        for( Thread t : al ) {
                                t.join();
                        }
                }
                catch( Exception e ) {
                        e.printStackTrace();
                }

        }
}

当它运行时,上面的线程同步方法都没有100%的时间工作.什么可能出错?



1> Martin Konec..:

您的问题是,在某些情况下,您的锁定锁定在不同的锁定对象实例上,因此它们实际上从不干扰其他锁定.

更改

Object o;

public static final Object o = new Object();

现在,您的所有synchronized语句都将尝试锁定同一个对象,并且将发生正确的锁争用.

这看起来很可疑:

while (SynchronObj.a < 65535) {...}

因为你正在读取没有同步的a的值.绝对是一个问题.

您的同步测试方法似乎也是通过搜索打印的重复输出.相反,尝试做

    public void run() {
            for (int i=0; i<10000; i++) {
                    adder();
            }
    }

因为您正在运行10个线程,所以只需验证最终答案是否正确10000*10.任何更少/更多将暗示不正确的线程同步.


在没有同步对象的情况下,也可以将方法`adder()`更改为静态同步
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有