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