java线程同步的几种方式
1、使用synchronized包裹代码块或者修饰方法
java的每个对象都有一个内置锁,要执行synchronized代码块必须获得内置锁。
2、使用wait/notify等待唤醒
3、使用特殊域变量volatile关键字修饰变量
4、使用重入锁ReentrantLock
ReenTrantLock lock = new ReenTrantLock();
lock.lock();
lock.unlock();
5、使用ThreadLocal局部变量
如果使用ThreadLocal管理变量,每个线程访问该变量都会获得该变量的副本,副本与副本之间相互独立,这样线程与线程之间就互不影响,解决多线程访问变量冲突的问题,这是以空间换时间
6、使用阻塞式队列实现同步
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
queue.put(x) -->向队尾添加元素,当队列满时阻塞
queue.take() -->移除并返回队头元素,当队列为空时阻塞
实例一:
用两个线程一个对变量执行加一一个对变量执行减一操作,实现线程同步。
这里使用内部类和synthronized同步代码块和同步方法分别实现
package com.hy.springmvc.thread; public class ThreadAddSub { private int i = 0; private synchronized void add() { i++; System.out.println(Thread.currentThread().getName() + "--add i=" +i); } private void add1() { synchronized (this) { i++; System.out.println(Thread.currentThread().getName() + "--add i=" +i); } } private synchronized void sub() { i--; System.out.println(Thread.currentThread().getName() + "--sub i=" +i); } private void sub1() { synchronized (this) { i--; System.out.println(Thread.currentThread().getName() + "--sub i=" +i); } } class ThreadAdd implements Runnable{ @Override public void run() { for (int i = 0; i < 21; i++) { add1(); } } } class ThreadSub implements Runnable { @Override public void run() { for (int i = 0; i < 21; i++) { sub1(); } } } public static void main(String[] args) { ThreadAddSub addSub = new ThreadAddSub(); ThreadAdd add = addSub.new ThreadAdd(); ThreadSub sub = addSub.new ThreadSub(); Thread t1 = new Thread(add); t1.start(); Thread t2 = new Thread(sub); t2.start(); } }
执行结果分析:
当加和减的此时相等时,最终变量一定是0
注意:
内部类的使用方法:
静态内部类(使用static修饰的内部类):B b = A.new B();
非静态内部类:A a = new A(); B b = a.new B();
邮箱:wangh_2@sina.com