线程同步
- 在多线程程序中,会出现多个线程抢占一个资源的情况,这时间有可能会造成冲突,也就是一个线程可能还没来得及将更改的 资源保存,另一个线程的更改就开始了。可能造成数据不一致。因此引入多线程同步,也就是说多个线程只能一个对共享的资源进行更改,其他线程不能对数据进行修改。
- 1.如下一个两个线程对一个银行账户进行存钱的小实例,其中使用synchornized修饰方法实现线程的同步
- 代码如下:
class bank{
private int count=100;
public synchronized void dispit() {
count+=10;
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
this.count = count;
this.textarea = textarea;
}
public void run() {
for(int i=0; i<10; i++) {
count.dispit();
textarea.APPend("账户余额为:"+count.getcount()+"\n");
}
}
}
2.同步是一种高开销的操作,因此应该尽量减少同步内容,因此也可以使用修饰代码块来代替修饰整个方法。
class bank{
private int count=100;
public void dispit() {
synchronized(this) {
count+=10;
}
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
this.count = count;
this.textarea = textarea;
}
public void run() {
for(int i=0; i<10; i++) {
count.dispit();
textarea.append("账户余额为:"+count.getcount()+"\n");
}
}
}
3.使用volatile修饰数据,对于当下问题,只用使用volatile来修饰账户的余额变量即可。该修饰词是对域变量的访问提供了以这种防锁机制,相当于告诉虚拟机,该域的变量可能被更改。因此每次使用该域都要重新计算,而不是从寄存器中取出数据。从而实现线程的同步。该修饰词不能修改final类型变量
class bank{
private volatile int count=100;
public void dispit() {
count+=10;
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
this.count = count;
this.textarea = textarea;
}
public void run() {
for(int i=0; i<10; i++) {
count.dispit();
textarea.append("账户余额为:"+count.getcount()+"\n");
}
}
}
4.使用重入锁实现线程同步。使用类ReentrantLock类来定义锁,其中lock()方法为打开锁,unlock()方法为关闭锁
类似于synchronized修饰方法有一样功能。使用锁时间需要注意应该及时放开锁,不然会进入死锁状态。一般是在finally中释放锁
class bank{
private volatile int count=100;
private Lock lock = new ReentrantLock();
public void dispit() {
lock.lock();
try {
count+=10;
}finally{
lock.unlock();
}
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
this.count = count;
this.textarea = textarea;
}
public void run() {
for(int i=0; i<10; i++) {
count.dispit();
textarea.append("账户余额为:"+count.getcount()+"\n");
}
}
}
代码的输出结果如下:
可以看到,每次增加10 的时间只有一个线程在进行,也就是线程的同步
5.使用Threadlocal类来管理。不过该方法和同步机制不相同。该类管理的变量在每个线程中都有自己的副本,副本之间相互独立,因此获得的结果和其他不同。
class bank{
private static ThreadLocal<integer> count = new ThreadLocal() {
protected Integer initialValue() {
return 100;
}
};
private Lock lock = new ReentrantLock();
public void dispit() {
lock.lock();
try {
count.set(count.get()+10);
}finally{
lock.unlock();
}
}
public int getcount() {
return count.get();
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
this.count = count;
this.textarea = textarea;
}
public void run() {
for(int i=0; i<10; i++) {
count.dispit();
textarea.append("账户余额为:"+count.getcount()+"\n");
}
}
}
结果如图:
可以看到,在改程序中,好比两个账户相互独立,互不干扰一样。同样解决了相同的变量访问冲突问题。
相关阅读
linux利用setpriority调整线程优先级,测试优先级对线程
以下测试是为了验证setpriority函数对线程是否有效,理论上linux kernel是不区分调度是不区分线程和进程的。用户线程和进程的区别
进程和程序区别和联系表现在以下方面:1)程序只是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。而进程则不同
本文档是自己所整理的一份文档,部分是原创,还转贴了网上的一此资料(已经标明了),(难点是多线程的编写),是有源代码的,大家可以作为参
java中Executor框架之ThreadPoolExcutor和ScheduledTh
转载自: https://blog.csdn.net/javazejian/article/details/50890554 java多线程-概念&创建启动&中断&守护线程&
线程属性pthread_attr_t简介 参考资料: 1,https://blog.csdn.net/sinat_36184075/article/details/71598639 2,https://blog.csdn.n