1.同步代码块
用Synchronied来修饰的代码块,排队执行,线程安全,但效率低下。
线程不安全情况,最终卖出-1张票
public static void main(String[] args) {
Runnable r = new Ticket();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
static class Ticket implements Runnable{
private int num = 10;
@Override
public void run() {
while (true) {
if (num>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName() + "卖出去一张票" + num);
}
}
}
}
使用Synchronied来使线程安全
public static void main(String[] args) {
Runnable r = new Ticket();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
static class Ticket implements Runnable{
private int num = 10;
private Object o = new Object();
@Override
public void run() {
while (true) {
synchronized (o){
if (num>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName() + "卖出去一张票" + num);
}
}
}
}
}
2.同步方法
用Synchronied来修饰的方法,排队执行,线程安全,但效率低下。
同步方法中不是静态的方法,锁的引用是this,静态的方法,锁的引用是类名.class。
线程不安全状况如上
使用Synchronied来使线程安全
public static void main(String[] args) {
Runnable r = new Ticket();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
static class Ticket implements Runnable{
private int num = 10;
@Override
public void run() {
while (true) {
boolean haha = haha();
if (!haha){
break;
}
}
}
public synchronized boolean haha(){
if (num>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName() + "卖出去一张票" + num);
return true;
}
return false;
}
}
3.显示锁lock
需要new出锁对象在需要上锁的地方上锁。
public static void main(String[] args) {
Runnable r = new Ticket();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
}
static class Ticket implements Runnable{
private int num = 10;
Lock l = new ReentrantLock();
@Override
public void run() {
while (true) {
l.lock();
if (num>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
System.out.println(Thread.currentThread().getName() + "卖出去一张票" + num);
}else {
break;
}
l.unlock();
}
}
}
4.lock和Synchronied
synchronized是关键字,Lock是接口,二者均可实现线程同步;
synchronized执行完自动释放锁,Lock需要程序员手动释放锁,不然可能出现死锁情况;
5.公平锁和非公平锁
公平锁:线程一个接一个的排队执行,先来的线程先执行。
非公平锁:线程一起抢,谁抢到谁执行。
JAVA中默认的是非公平锁
可在创建lock时传入true来使其变成公平锁
Lock l = new ReentrantLock(true);