java多线程同步机制的实现方式总结
来源:互联网 发布:ubuntu教程 百度云 编辑:程序博客网 时间:2024/06/01 09:37
关于多线程同步,拿一个比较经典的题目来说,卖火车票,假设有3个线程,代表3个售票窗口
一共是100张火车票,由三个窗口共同售卖,那么这100张票就是三个线程的共享数据,因为
每一张票都有唯一性,同一张票只能由一个售票窗口售出,那么就需要要求给线程加同步机制
搜集了一些资料,针对共享数据的同步,目前我总结了3种方法:
- synchronized锁住线程内的共享变量
- volatile标识共享变量
- Lock lock = new ReentrantLock();通过重入锁的方式
对比来看,1是利用了synchronized的锁机制,同一时刻,只有持有锁的线程有机会修改数据,修改完即释放锁,方案2虽然不是锁的机制,但是从感觉上来说和锁定共享变量实质一样,只是事实上是告诉jvm此变量在寄存器内的值不可信,应该去主内存去查找,也就是要重新计算.方案3是jdk5.0引入的,位于java.util.concurrent.locks中的一个可重入锁类。在高竞争条件下有更好的性能,且可以中断。深入剖析ReentrantLock的源码有助于我
们了解线程调度,锁实现,中断,信号触发等底层机制,实现更好的并发程序。
这里我在AS里通过代码实际测试了一下,1.2的效率是差不多的,3的效率明显比12的效率高
代码简单,就全部贴出来了(join方法实现的同步其实和本例子无关,但也是一种同步的场景,就是一个线程等待另一个线程的结果):
package com.practice.dev.mythread;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MainActivity extends AppCompatActivity { private Runnable runnable1; private MyRunnable2 runnable2; private MyRunnable3 runnable3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); runnable1 = new MyRunnable(); runnable2 = new MyRunnable2(); runnable3 = new MyRunnable3(); carry1();//runnable实现的多线程同步,通过synchronized锁定共享数据,单个线程执行完便释放锁,效率一般 // carry2();//通过volatile实现的多线程同步,此关键字只能修饰变量,不能修饰类和方法,效率一般 // carry3();//通过重入锁的方式实现线程同步,此方式线程执行效率较高,几乎是同时执行,但数据也实现了同步操作 // joinCarry();//join方法确保当前线程执行过程中所持有的变量只能被自己拥有,同时有阻塞的感觉,只有当前线程结束才会向下执行 } private void carry3() { new Thread(runnable3).start(); new Thread(runnable3).start(); new Thread(runnable3).start(); } private void carry2() { new Thread(runnable2).start(); new Thread(runnable2).start(); new Thread(runnable2).start(); } private void carry1() { new Thread(runnable1).start(); new Thread(runnable1).start(); new Thread(runnable1).start(); } /** * a.volatile关键字为域变量的访问提供了一种免锁机制, * b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, * c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 * d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 */ class MyRunnable implements Runnable{ private volatile int ticket = 100;//不用锁,只需要volatile即可,与synchronized区别是volatile只能修饰变量,不能修饰方法和类 @Override public void run() { try { while (ticket>0){ Log.d("ticket",Thread.currentThread().getName()+"当前卖第"+ticket+"张"); ticket--; Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } class MyRunnable2 implements Runnable{ private int ticket = 100; @Override public void run() { try { while (ticket>0){ synchronized (MyRunnable.class){ Log.d("ticket",Thread.currentThread().getName()+"当前卖第"+ticket+"张"); ticket--; } Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 重入锁的方式实现同步,此场景功能类似volatile,但是效率比voLatile高 */ class MyRunnable3 implements Runnable{ private int ticket = 100; private Lock lock = new ReentrantLock(); @Override public void run() { try { while (ticket>0){ lock.lock(); Log.d("ticket",Thread.currentThread().getName()+"当前卖第"+ticket+"张"); ticket--; lock.unlock(); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); }finally { } } } private int a; private void joinCarry() { Runnable r = new ThreadTest(); Thread t1 = new Thread(r); t1.start(); try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } Log.d("ticket",a+""); } class ThreadTest implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { inc(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } private synchronized void inc() { a++; } }}
0 0
- java多线程同步机制的实现方式总结
- Java多线程的同步机制
- Java多线程的同步机制
- java多线程的同步机制
- 多线程同步实现的方式
- java 多线程 同步机制 总结(一)
- java 多线程 同步机制 总结(二)
- Java多线程同步的方式
- java同步机制的几种实现方式
- Java多线程的同步总结
- 多进程间通信方式和多线程同步机制总结
- 多进程间通信方式和多线程同步机制总结
- 多进程间通信方式和多线程同步机制总结
- 多进程间通信方式和多线程同步机制总结
- 多进程间通信方式和多线程同步机制总结
- java多线程同步机制
- java多线程同步机制
- Java多线程同步机制
- springMVC 获取请求参数的方法
- 十分钟正则快速入门
- 为什么我们有必要重新思考和定义“运营”?
- VR真如此吃香?未来五年市场都将保持上升趋势
- Linux yum安装MySQL5.7
- java多线程同步机制的实现方式总结
- Linux常用命令——帮助命令
- Solr学习总结(三)建立第一个索引
- Operators in MXNet-Dropout
- andorid apk 反编译
- 线段树的极值查找
- curl之get请求
- 高并发Java 二 多线程基
- 杭电acm 1230 火星A+B