同步锁:当在一个java虚拟机多个线程操作一个变量的时候就会出现线程安全问题,这个时候就会用到同步锁。
同步锁的解决方式:
先看下一个线程异常的售票
public class ThreadSafe {
public static void main(String[] args) {
MyThread t1 = new MyThread("窗口一");
MyThread t2 = new MyThread("窗口一");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread{
private static int count = 10;
public MyThread(String name) {
super(name);
}
@Override
public void run() {
while(count > 0) {
System.out.println(Thread.currentThread().getName()+"售出:"+(count--) +" 票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
synchronized 解决的三种方式:1)使用synchronized 静态代码块 2)synchronized 同步方法 3)synchronized 同步类
public class ThreadSafe {
public static Object obj = new Object();
public static void main(String[] args) {
MyThread t1 = new MyThread("窗口一");
MyThread t2 = new MyThread("窗口一");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread{
private static int count = 10;
public MyThread(String name) {
super(name);
}
@Override
public void run() {
while(count > 0) {
//静态代码块锁,定义同一个对象
synchronized (obj) {
System.out.println(Thread.currentThread().getName()+"售出:"+(count--) +" 票");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//使用synchronized 定义的方法锁
public class ThreadSafe1 {
public static Object obj = new Object();
public static void main(String[] args) {
//这个地方必须是对同一个对象进行操作
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread, "窗口一");
Thread t2 = new Thread(myThread, "窗口二");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread implements Runnable{
private static int count = 10;
//方法锁
public synchronized void increse() {
System.out.println(Thread.currentThread().getName()+"售出:"+(count--) +" 票");
}
@Override
public void run() {
while(count > 0) {
increse();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//使用类锁
public class ThreadSafe2 {
public static void main(String[] args) {
MyThread t1 = new MyThread("窗口一");
MyThread t2 = new MyThread("窗口一");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread{
private static int count = 10;
public MyThread(String name) {
super(name);
}
public static synchronized void increase() {
System.out.println(Thread.currentThread().getName()+"售出:"+(count--) +" 票");
}
@Override
public void run() {
while(count > 0) {
//静态代码块锁,定义同一个对象
increase();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
2.使用lock的解决方式
//使用类锁
public class ThreadSafe3 {
public static Lock lock = new ReentrantLock();
public static void main(String[] args) {
MyThread t1 = new MyThread("窗口一");
MyThread t2 = new MyThread("窗口二");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyThread extends Thread{
private static int count = 10;
public MyThread(String name) {
super(name);
}
public static void increase() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"售出:"+(count--) +" 票");
}catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
@Override
public void run() {
while(count > 0) {
//静态代码块锁,定义同一个对象
increase();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
异步锁:就是多个java 虚拟机或者说是服务器,操作同一个变量是,会出现线程安全问题,使用需要使用异步锁来处理。
1)数据库 乐观锁 悲观锁 唯一标示 不推荐使用,容易出现锁表,出现死锁。
2)Redis 分布式锁 ,就是设置一个flag标识,当一个服务拿到锁以后立即把对应的标识设置为false 用完后释放锁,并把标识修改为true 详见如下:
3)使用dubbo zookeeper (共享锁,排它锁),这里就根据自己的情况,共享锁还是会出现阻塞的情况,排它锁就是会生成很多临时的节点,谁先获取最小的序号标识谁就先获取到锁。