线程同步
1.隐式同步锁synchronized
1.同步代码块
2.同步方法
同步方法 必须放在 资源类中,确保this 只有一份
有锁, 但是锁默认是 this
非静态同步方法, 锁是 this, 静态同步方法,锁 是 类.class
1.有五个人同时过一个独木桥,一个独木桥同时只能允许一个人通过。每一个人通过独木桥的时间是随机在 [5,10] 秒,输出这个独木桥上每一个人的通过详情,
例如:张三开始过独木桥了… 张三通过独木桥了!
1.同步代码块
public class Test {
public static void main(String[] args) {
Bridge t = new Bridge();
Thread t1 = new Thread(t, "张三");
Thread t2 = new Thread(t, "李四");
Thread t3 = new Thread(t, "王五");
Thread t4 = new Thread(t, "赵六");
Thread t5 = new Thread(t, "田七");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
class Bridge implements Runnable {
@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "开始过独木桥了");
int num = (int) (Math.random() * 6 + 5);
try {
Thread.sleep(num * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "通过独木桥了");
}
}
}
2.同步方法
public class Test {
static Object obj = new Object();
public static void main(String[] args) {
Qiao t = new Qiao();
Thread t1 = new Thread(t, "张三");
Thread t2 = new Thread(t, "李四");
Thread t3 = new Thread(t, "王五");
Thread t4 = new Thread(t, "赵六");
Thread t5 = new Thread(t, "田七");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
class Qiao implements Runnable {
@Override
public void run() {
bridge();
}
public static synchronized void bridge() {
// Qiao.class 永远唯一, 符合锁的要求
System.out.println(Thread.currentThread().getName() + "开始过桥了");
int i = (int) (Math.random() * (10 - 5 + 1) + 5);
try {
Thread.sleep(i * 1000);// 会释放cpu, 但是不会释放锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "过去了");
}
}
例:2.有一张银行卡, 张三,李四所有,张三 往里边存钱 每次存10000,一共存10次,李四 取钱, 每次取10000, 一共取10次
同步代码块
public class Test {
public static void main(String[] args) {
Card card = new Card();
Zs zs = new Zs(card);
Ls ls = new Ls(card);
Thread thread = new Thread(zs);
Thread thread2 = new Thread(ls);
thread.start();
thread2.start();
}
}
class Card {
int money;
public Card(int money) {
super();
this.money = money;
}
public Card() {
super();
}
}
class Zs implements Runnable {
Card card;
public Zs(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
card.money += 10000;
System.out.println("张三存了10000,还剩" + card.money);
}
}
}
}
class Ls implements Runnable {
Card card;
public Ls(Card card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
card.money -= 10000;
System.out.println("李四取了10000,还剩" + card.money);
}
}
}
}
同步方法
public class Test2 {
public static void main(String[] args) {
Card2 card = new Card2();
Zs2 zs2 = new Zs2(card);
Ls2 ls2= new Ls2(card);
Thread thread = new Thread(zs2);
Thread thread2 = new Thread(ls2);
thread.start();
thread2.start();
}
}
// 资源类
class Card2 {
int money;
public synchronized void take() {// this
money -= 10000;
System.out.println("李四取了10000,还剩" + money);
}
public synchronized void save() {// this
money += 10000;
System.out.println("张三存了10000,还剩" + money);
}
}
// 操作类
class Zs2 implements Runnable {
Card2 card;
public Zs2(Card2 card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
card.save();
}
}
}
// 操作类
class Ls2 implements Runnable {
Card2 card;
public Ls2(Card2 card) {
super();
this.card = card;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
card.take();
}
}
}
2.显式同步锁Lock
需要手动new出对象,只能有一个对象
需要解锁,lock.unlock
加try-finally,目的是为了一定进行解锁
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
//创建一次资源类对象
Ticket ticket = new Ticket();
//创建线程对象
Thread t = new Thread(ticket, "窗口一");
Thread t2 = new Thread(ticket, "窗口二");
Thread t3 = new Thread(ticket, "窗口三");
Thread t4 = new Thread(ticket, "窗口四");
t.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket implements Runnable{
int ticket = 100;
ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
//开始加锁
lock.lock();
if (ticket>0) {
ticket--;
System.out.println(Thread.currentThread().getName()+"买了一张票,还剩"+ticket+"张票");
}else {
break;
}
} finally {
// 解锁
lock.unlock();
}
}
}
}
3.懒汉设计模式加锁
每个类的模板都是唯一的
添加了一把锁,做了双重检查(虽然加了一把锁,但是做了双重检查,外层检查目的是提高执行效率)
public class LazyInstance {
private LazyInstance() {
}
private static LazyInstance instance = null;
public static LazyInstance getInstance() {
if (instance == null) {
synchronized (LazyInstance.class) {
if (instance == null) {
instance = new LazyInstance();
}
}
}
return instance;
}
}
4.死锁
两个(多个线程)持有着对方想要的资源不放,但是还想要对方手里的资源
写代码的时候一定要避免
如果遇到需要有同步代码块嵌套的情况, 持有锁的顺序应该一致
public class Test {
public static void main(String[] args) {
Zs zs = new Zs();
Ls ls = new Ls();
zs.start();
ls.start();
}
}
class Lock{
static Object locka = new Object();
static Object lockb = new Object();
}
class Zs extends Thread{
@Override
public void run() {
synchronized (Lock.locka) {
System.out.println("张三拥有了筷子a,准备去抢筷子b");
synchronized(Lock.lockb) {
System.out.println("张三抢到了两根筷子,张三吃饭");
}
}
}
}
class Ls extends Thread{
@Override
public void run() {
synchronized (Lock.locka) {
System.out.println("李四拥有了筷子a,准备去抢筷子b");
synchronized(Lock.lockb) {
System.out.println("李四抢到了两根筷子,张三吃饭");
}
}
}
}