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();