多线程编程中保证线程安全(1)

来源:互联网 发布:kmp算法匹配过程 编辑:程序博客网 时间:2024/06/15 21:26

今天上课的时候,在测试一段代码时想到了一点简单的保证线程安全的东西。

首先是待测试的代码:

<pre name="code" class="java">
public class ThreadCount {public static void main(String[] args) {Thread[] threads=new Thread[10000];for (int i = 0; i < 10000; i++) {threads[i]=new AThread();threads[i].start();}}}class AThread extends Thread{public void run(){Counter counter = new Counter();System.out.println(Counter.calNum());}}class Counter{private static long num;public Counter(){    num++;}public static long calNum(){    return num;}}


很明显,这段代码中共享的临界资源就是Counter中num变量,在不同的线程中对num进行++操作,但是在输出的时候不能及时更新。

所以我们要处理的就是如何保持保证这个num的同步使用(只有在输出之后才允许其他线程使用Counter的构造方法)。

方法一:直接锁住Counter这个类(其实就是保证其中的static变量只能有一个线程在访问)

public class ThreadCount {public static void main(String[] args) {Thread[] threads=new Thread[10000];for (int i = 0; i < 10000; i++) {threads[i]=new AThread();threads[i].start();}}}class AThread extends Thread{public void run(){synchronized (Counter.class) {Counter counter = new Counter();System.out.println(Counter.calNum());}}}class Counter{private static long num;public Counter(){num++;}public static long calNum(){    return num;}}
方法二:(构造一个监视对象专用用来保证代码的连续运行,这一点在很多时候很有用;并且有了这个监视对象之后,可以灵活地对代码块进行同步),从下面的例子中我们可以看到,如果这些线程都公用一个ThreadMonitor则可以随时利用这个Object来对代码块进行锁定。
public class ThreadCount {public static void main(String[] args) {Object ThreadMonitor = new Object();Thread[] threads=new Thread[10000];for (int i = 0; i < 10000; i++) {threads[i]=new AThread(ThreadMonitor);threads[i].start();}}}class AThread extends Thread{Object ThreadMonitor = null;public AThread(Object ThreadMonitor){this.ThreadMonitor = ThreadMonitor;}public void run(){synchronized (ThreadMonitor) {Counter counter = new Counter();System.out.println(Counter.calNum());}}}class Counter{private static long num;public Counter(){num++;}public static long calNum(){    return num;}}

方法三:其实这种方法和方法二没有什么区别,可以直接使用Lock对象来对代码块,进行锁定,但是由于是多个进程,所以要把Lock对象设为静态static变量,这样所有的线程都是共用一个Lock对象,从而形成互斥访问。

public class ThreadCount {public static void main(String[] args) {Thread[] threads=new Thread[10000];for (int i = 0; i < 10000; i++) {threads[i]=new AThread();threads[i].start();}}}class AThread extends Thread{private static Lock runlock = new ReentrantLock();public void run(){runlock.lock();try{Counter counter = new Counter();System.out.println(Counter.calNum());} finally{runlock.unlock();}}}class Counter{private static long num;public Counter(){num++;}public static long calNum(){    return num;}}
现在对多线程的理解还很幼稚,所以应该多想想如何使用。其实这里的方法二是一种很好的方式,对于临界资源的访问可以使用一个Monitor来监视,这样就能互斥访问。

0 0
原创粉丝点击