关于线程之间的调配使用,我们已经初步了解的同步的理念。那么,在实际中又有哪些方法可以实现线程的同步呢?这里我们结合了以往所学的synchronized、Lock和volatile知识点,分别是两种关键字和锁的原理,可以实现多个线程进行同步的 *** 作,下面我们就分别进行方法的讲解。
1.synchronized关键字
Synchronized修饰整个方法。
package threadTest; public class Bank { private int count =0;//账户余额 //存钱 public synchronized void addMoney(int money){ count +=money; System.out.println(System.currentTimeMillis()+"存进:"+money); } //取钱 public synchronized void subMoney(int money){ if(count-money < 0){ System.out.println("余额不足"); return; } count -=money; System.out.println(+System.currentTimeMillis()+"取出:"+money); } //查询 public void lookMoney(){ System.out.println("账户余额:"+count); } }
再看看运行结果:
余额不足 账户余额:0 余额不足 账户余额:0 1441790837380存进:100 账户余额:100 1441790838380取出:100 账户余额:0 1441790838380存进:100 账户余额:100 1441790839381取出:100 账户余额:0
2.Lock
在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。
class Bank { private int account = 100; //需要声明这个锁 private Lock lock = new ReentrantLock(); public int getAccount() { return account; } //这里不再需要synchronized public void save(int money) { lock.lock(); try{ account += money; }finally{ lock.unlock(); } } }
3.volatile关键字
(1)volatile是变量修饰符,其修饰的变量具有可见性。
可见性就是说一旦某个线程修改了被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取的时候,可以立即获取修改之后的值。
在Java中为了加快程序的运行效率,对一些变量的 *** 作通常是在该线程的寄存器或CPU缓存上进行的,之后才会同步到主存中,而加了volatile修饰符的变量则是直接读写主存。
(2)volatile可以禁止指令重排
指令重排是指编译器或者CPU为了提高程序的运行效率,可能会对输入的代码进行优化,它不保证各个语句的执行顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码中的执行结果是一致的,应用条件是单线程条件,对于并发多线程的场景下,指令重排会产生不确定的结果。
以上就是线程同步在java中的 *** 作,这里我们推荐大家使用synchronized关键字,作为主流方法被很多人所接受,其它两种方法可以了解一下。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)