java 线程同步互斥锁_Java04 线程同步问题解决——线程锁(同步锁、互斥锁)

目录

写在最前:

可能有误,请大家批评指正

一、线程切换

Java中,如果要实现在一个线程间的线程切换,需要在线程中使用Thread.yield()即可让出CPU时间。

二、线程锁(也叫同步锁、互斥锁)

线程锁可以在有效缩小同步范围的同时,尽可能的保证并发效率

2.1 使用synchronized关键字对方法进行加锁

对整个线程处理加锁(严重影响效率,不常用)

2.1.1 语法

public synchronized void test(){

}

2.1.2 案例

package com.javase.thread;

import javax.management.RuntimeErrorException;

/**

* 这个类主要讲了Sychronized关键字,给方法加了Synchronized关键字以后,线程在调用这个方法时,相当于对这个方法加了锁,

* 那么其他线程就不能调用这个方法了(处于阻塞状态)

*

* @author gupan

*

*/

public class ThreadSyncSychronized {

public static void main(String[] args) {

final Table2 table = new Table2();

Thread t1 = new Thread() {

public void run() {

while (true) {

try {

int bean = table.getBean();

Thread.yield(); // 线程切换语句,让出CPU时间

System.out.println(getName() + "," + table.getBean());

} catch (RuntimeErrorException e) {

System.out.println(getName() + "," + e);

break;

}

}

}

};

Thread t2 = new Thread() {

public void run() {

while (true) {

try {

int bean = table.getBean();

Thread.yield(); // 线程切换语句,让出CPU时间

System.out.println(getName() + "," + table.getBean());

} catch (RuntimeErrorException e) {

System.out.println(getName() + "," + e);

break;

}

}

}

};

t2.start();

t1.start();

}

}

class Table2{

// 桌子上有20元钱

private int beans = 20;

public synchronized int getBean() throws RuntimeErrorException{

if (this.beans == 1) {

throw new RuntimeErrorException(null, "地主家没有余粮了");

}

Thread.yield(); // 线程切换语句,让出CPU时间

return this.beans--;

}

}

2.2 使用synchronize关键字对线程方法中的某一部分加锁(同步块的方式)

2.2.1 语法

// 注意这里是this,可以写new Object(),但是这样起不到加锁的效果

// 也就是说,要实现加锁的效果,需要保证是对同一个对象(也就是保证synchronized后面所跟对象是同一个)加锁

synchronized(this){

···

// 加锁语句

}

2.2.2 案例

package com.javase.thread;

/**

* 这个类主要演示小范围的使用锁。尽可能的提高并发效率

*

* synchronized(this){

* ···

* // 加锁语句

* }

*

* @author Think

*

*/

public class ThreadSyncLock {

public static void main(String[] args) {

final Shop shop = new Shop();

Thread t1 = new Thread() {

public void run() {

shop.buy();

}

};

Thread t2 = new Thread() {

public void run() {

shop.buy();

}

};

t1.start();

t2.start();

}

}

class Shop{

public void buy() {

Thread t = Thread.currentThread();

try {

System.out.println(t.getName() + "正在挑衣服");

Thread.sleep(1000);

// 需要传入当前方法所属对象,所以这里要传入this

synchronized (this) {

System.out.println(t.getName() + "正在试衣服");

Thread.sleep(1000);

}

System.out.println(t.getName() + "结账离开");

Thread.sleep(1000);

}catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

}

2.3 静态方法加锁

如果对静态方法加了synchronized关键字,由于静态方法只有一份,整个方法一定是加了互斥锁

package com.javase.thread;

import com.javase.string.Object;

/**

* 静态方法的同步

* 当一个静态方法被synchronized修饰以后,那么该方法就是同步方法,由于静态方法从属类,

* 全局就一份,所以同步的静态方法一定具有同步效果,与对象无关

*

* @author gupan

*

*/

public class ThreadSyncStatic {

public static void main(String[] args) {

Thread t1 = new Thread() {

public void run() {

Foo.dosome();

}

};

Thread t2 = new Thread() {

public void run() {

Foo.dosome();

}

};

t1.start();

t2.start();

}

}

class Foo{

public static synchronized void dosome() {

try {

Thread t = Thread.currentThread();

System.out.println(t.getName() + "正在等待运行dosome方法");

Thread.sleep(1000);

System.out.println(t.getName() + "正在运行dosome方法");

Thread.sleep(1000);

System.out.println(t.getName() + "执行dosome方法完毕");

}catch (Exception e) {

// TODO: handle exception

}

}

}

运行结果:

Thread-1正在等待运行dosome方法

Thread-1正在运行dosome方法

Thread-1执行dosome方法完毕

Thread-0正在等待运行dosome方法

Thread-0正在运行dosome方法

Thread-0执行dosome方法完毕

2.3 互斥锁

2.3.1 同步锁和互斥锁

同步锁和互斥锁原理相同,存在的是用法上的小差异。当两个线程调用同一段代码,并且,对于两个线程的同步监视器,看到的代码相同,那就是同步锁;但是,对于几段代码,用一个同步监视器进行访问,几段代码不能同时执行,就是互斥锁

package com.javase.thread;

/**

* 这段代码主要演示互斥锁的使用

* 使用synchronized修饰这段代码之后,只要他们同步监视器对象相同,那么这几段代码见就是互斥关系,多个线程不能同时执行这些代码

*

* @author gupan

*

*/

public class ThreadSyncMatual {

/**

* 线程t1和t2不能同时调用methodA或methodB方法,实现互斥关系

*

* @param args

*/

public static void main(String[] args) {

Boo boo = new Boo();

Thread t1 = new Thread() {

public void run() {

boo.methodA();

}

};

Thread t2 = new Thread() {

public void run() {

boo.methodB();

}

};

t1.start();

t2.start();

}

}

class Boo{

public void methodA(){

try{

Thread t = Thread.currentThread();

System.out.println(t.getName() + "正在执行A方法");

Thread.sleep(1000);

System.out.println(t.getName() + "执行A方法完毕");

}catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

public void methodB(){

try{

Thread t = Thread.currentThread();

System.out.println(t.getName() + "正在执行B方法");

Thread.sleep(1000);

System.out.println(t.getName() + "执行B方法完毕");

}catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值