Java多线程基础学习(二)
9. 线程安全/共享变量——同步
当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次。这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”。
为了解决线程安全的问题,我们可以使用“同步”来控制线程访问。当一个线程在使用这个共享资源(不仅仅是变量,还可以是集合、对象等)的时候,其他线程就无法访问。
package threadStudy; public class ThreadSynchronizedTest { public static void main(String[] args) throws InterruptedException{ int i=0; ObjA o = new ObjA(i); TheThread theThread1 = new TheThread(o); TheThread theThread2 = new TheThread(o); theThread1.start(); theThread2.start(); } static class TheThread extends Thread{ private ObjA objA; public TheThread(ObjA objA){ this.objA = objA; } public void run(){ objA.method(); } } static class ObjA{ int i; public ObjA(int i){ this.i = i; } synchronized public void method(){ for (int j=0;j<10;j++){ i++; System.out.println(Thread.currentThread().getName()+ ": " + i); try{ Thread.sleep(200); }catch(InterruptedException e){ e.printStackTrace(); } } } } }
以上述代码为例,如果加了关键字synchronized,则一个线程在使用共享资源o时,另一个线程必须等到前一个线程使用完,才能使用。
加synchronized的输出结果:
而不加synchronized的输出结果:
10. 容器类并发问题的同步解决方法
JDK中提供了并发容器,可以直接帮我们解决容器类出现的并发问题。它们大部分都存在java.util.concurrent这个包中,包括:ConcurrentHashmap,CopyOnWriteArrayList,ConcurrentLinkedQueue,BlockingQueue,ConcurrentSkipListMap。下面是使用ConcurrentHashmap解决Map容器并发问题的例子:
1 package threadStudy; 2 3 import java.util.Collections; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 public class ThreadConcurrencyCollectionTest { 8 9 public static void main(String[] args) { 10 Thread thread1 = new Thread(new HashTest.AddThread(0), "T0"); 11 Thread thread2 = new Thread(new HashTest.AddThread(1), "T1"); 12 thread1.start(); 13 thread2.start(); 14 15 } 16 17 } 18 19 class HashTest{ 20 //static Map<String, String> map = new HashMap<String, String>(); 21 static Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>()); 22 public static class AddThread extends Thread{ 23 private int start; 24 public AddThread(int start){ 25 this.start = start; 26 } 27 public void run(){ 28 for (int i=start; i<10000; i+=2){ 29 System.out.println(Integer.toString(i)); 30 map.put(Integer.toString(i), Integer.toBinaryString(i)); 31 } 32 } 33 34 } 35 }
zni.feng@gmail.com