一、条件变量
条件变量实现了java.util.concurrent.locks.Condition接口,条件变量的实例化就是通过一个Lock对象上调用newCondition()方法获得的,这样条件就和一个锁绑定起来了。因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。
条件变量的出现是为了更精细的控制线程等待与唤醒,一个锁可以有多个条件,每个条件上有多个线程等待,通过await()方法,可以让线程在该条件下等待。当调用signalAll()方法时,又可以唤醒该条件下等待的线程。条件变量比较抽象,原因是它不是自然语言中的条件概念,而是控制程序的一种手段。
看个例子,有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,但取款有限制,不能透支,任何试图透支的操作都将等待里面有足够的存款时才执行操作。
CaseTest.java
结果为:
如果不用条件变量和锁,如何实现此功能呢?
CaseTest.java
第二种方式是用同步方法的第一种方法,以前说过这种方法不如第二种好,下面改进一下该同步的程序:
CaseTest.java
二、Volatile变量
具体的内容,详见 JAVA理论与实践:正确使用Volatile变量
三、原子量
所谓原子量就是操作变量的操作是“原子的”,该操作不可再分,因此线程是安全的。volatile、synchronized关键字来解决并发访问的安全问题,但这样太麻烦。有一个用来进行单变量多线程并发安全访问的工具包java.util.concurrent.atmoic。
Test.java
结果为
这个例子是个反例,可见到虽然使用了原子量,但是并发访问还是有问题,那么问题在哪?原子量虽然可以保证单个变量在某一个操作过程安全,但无法保证整个代码块,或者说整个程序的安全。因此,通常可以使用锁等同步机制控制整个程序的安全性。
Test.java
结果为:
此时,加入了一个对象锁,来控制并发访问的控制,不管程序运行多少次,结果都是一样的。有关原子的用法仅仅保证变量操作的原子性,但是需要考虑整个过程的线程安全性。
四、信号量
一个信号量管理很多的许可证,为了获取信号量,线程通过调用acquire请求许可。Java信号量实际上是一个功能完毕的计数器,并由此限制了通过的线程数量,其他线程可以通过调用release释放许可。
它对控制一定资源的消费与回收有着重要意义,信号量常常用于多线程的代码中,并能监控有多少数目的线程等待获取资源,并且通过信号量可以得知可用资源的数目等等,这里强调数目二字,并不是指有哪些在等待,哪些资源可用。例子:
SignalTest.java
结果为:
信号量仅仅是对池资源进行监控,但不能 保证线程的安全,因此,应该自己控制线程的安全访问资源。
五、线程池
线程池的思想还是一种对象池的思想,开辟一块内存空间,里面存放众多的(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完线程对象归池,这样可以避免反复创建线程对象带来的性能开销,节约系统资源。
线程池分为固定尺寸的线程池、可变尺寸线程池。
1、固定大小的线程池
2、单任务线程池
在上一例修改一行pool对象的代码为:
以上两种情况都是大小固定的,当要加入的池的线程(或任务)超过池最大尺寸的时候,则入此线程池需要排队等待。
3、可变尺寸的线程池
4、延迟线程池
5、单任务延迟线程池
在4的代码基础上修改为:
6、自定义线程池
创建自定义线程池的构造方法很多,本例中的含义如下:
虽然自定义线程池麻烦点,但是可以获取当前线程池的尺寸、正在执行任务的线程数、工作队列等。
六、障碍器
当计算一个大的任务时,常常需要分配好多子任务去执行,只有当所有子任务执行完时,才能执行主任务,这时候需要借助障碍器。
当神已无能为力,那便是魔渡众生
到此这篇java调用dll动态库多线程数据不对(java调用dll动态库多线程数据不对怎么办)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/sjkxydsj/66589.html