JAVA 线程同步 synchronized
来源:互联网 发布:游族网络最新消息 编辑:程序博客网 时间:2024/05/19 23:57
先举个例子说明一下不采用线程同步带来的后果,假设现在我手上有20张票,雇佣2个人帮我卖票(2个人共享20张票),假设就剩最后一张了,那么如果一个人先看自己手上还有票,就卖给别人了,如果判断和卖个别人中间所花费时间过长,线程切给另一个人,此时票数还是2张,他认为也可以卖,就卖出了两张票。
public class testdouble implements Runnable{ private int total=20;//一共20张票 public void run() { while(true){if (total>0){//如果还有票try {Thread.sleep(100);//让当前操作延迟一段时间(假设某段耗时较长的操作)} catch (InterruptedException e) {e.printStackTrace();}total--;System.out.println("现在还有:"+total+"张票");}else break; } } public static void main(String[] args) {testdouble t=new testdouble();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();t2.start();}}
现在还有:18张票现在还有:18张票现在还有:17张票现在还有:16张票现在还有:15张票现在还有:14张票现在还有:13张票现在还有:12张票现在还有:11张票现在还有:10张票现在还有:9张票现在还有:8张票现在还有:7张票现在还有:6张票现在还有:5张票现在还有:4张票现在还有:3张票现在还有:2张票现在还有:1张票现在还有:0张票现在还有:-1张票
为了避免这种情况的发生,我们使用synchronized进行修饰。
当一个线程拿到 synchronized修饰的对象时,其他也需要拿到这个对象才能运行的线程不能执行了。
(线程——对象)
public class testdouble2 implements Runnable{ private int total=20;//总共有20张票 public synchronized void run(){ while(true){ if (total>0){ try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} total--; System.out.println("现在还有:"+total+"张票"); } else{ break; } } } public static void main(String[] args) {testdouble2 t=new testdouble2();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();t2.start();}}
现在还有:19张票现在还有:18张票现在还有:17张票现在还有:16张票现在还有:15张票现在还有:14张票现在还有:13张票现在还有:12张票现在还有:11张票现在还有:10张票现在还有:9张票现在还有:8张票现在还有:7张票现在还有:6张票现在还有:5张票现在还有:4张票现在还有:3张票现在还有:2张票现在还有:1张票现在还有:0张票
或者采用以下方法:
public class testdouble2 implements Runnable{ private int total=20;//总共有20张票 public void run(){ String a="now ok"; while(true){ synchronized (a) {//添加线程同步 if (total>0){ try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} total--; System.out.println("现在还有:"+total+"张票"); } else{ break; } } } } public static void main(String[] args) {testdouble2 t=new testdouble2();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();t2.start();}}
比较奇妙的是以下方法:
public class testdouble2 implements Runnable{ private int total=20;//总共有20张票 public synchronized void run(){ String a="now ok"; while(true){ if (total>0){ try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} total--; System.out.println("现在还有:"+total+"张票"); } else{ break; } } } public static void main(String[] args) {Thread t1=new Thread(new testdouble2());//注意Thread t2=new Thread(new testdouble2());t1.start();t2.start();}}此种方法无法防止,理由是synchronized是拿到所修饰的对象,而这两个线程是分属两个不同的对象的(各自new 出来的),所以无法避免,这也就是说extends无法使用synchronized关键字实现线程共享(因为extends肯定是各自new出两个新对象)。
事实上,即使是i++也会导致不同步:
int i=0;public int getNext(){return i++;}
因为jvm首先在jvm堆给i分配一个内存存储场所,线程启动后会自动分配一片操作数栈,现将这个值读取到栈中操作再写回堆中,所以需要间隔一段时间,这段时间如果切换线程就会导致不同步。
总结:synchronized关键字实现线程共享的方法是获得类所对应的的对象,在自己使用时,避免其他线程使用该对象。
可以使用在方法上,也可以使用在对象上。
0 0
- java 线程同步 synchronized
- java 线程同步 synchronized
- java synchronized 线程同步
- Java 线程同步 synchronized
- Java线程同步synchronized
- java线程同步-synchronized
- java线程同步:synchronized
- java synchronized线程同步
- JAVA 线程同步 synchronized
- java 线程synchronized 线程同步
- java线程同步之synchronized
- Java 线程同步(synchronized)
- java 线程同步:synchronized 关键字
- java线程之同步synchronized
- java中synchronized,线程同步
- Java线程同步问题synchronized
- java线程同步 synchronized同步锁
- java 线程synchronized 线程同步
- Oracle 经由常规路径由 EXPORT:V11.02.00创建到导出文件IMP-00013: 只有 DBA 才能导入由其他 DBA 导出的文件IMP-00000:为成功终止导入
- STM32下载方法
- Unix操作系统的历史演变
- 模仿优酷视频截图功能
- [LeetCode]45. Jump Game II
- JAVA 线程同步 synchronized
- LeetCode 113. Path Sum II
- socket通信的遇到的问题1
- Codeforces Round #257 (Div. 1) C. Jzzhu and Apples(构造题,想法题,好题)
- 图论之拓扑排序
- HttpURLConnection用法详解
- 特殊排序
- 【LeetCode 4】 Median Of Sorted Array
- codevs 4175 二分+spfa判断