在多线程程序执行过程中,可能会涉及到两个或者多个线程试图同一时候訪问同一个资源。为了防止这样的情况的发生,必须在线程使用共享资源时给资源“上锁”,以阻挡其他线程的訪问。

而这样的机制也经常被称为相互排斥量。本文主要介绍它的两种方式synchronized和Lock 。

1、synchronized

当任务要运行被synchronizedkeyword保护的代码片段的时候,它会检查锁是否可用,然后获取锁。运行代码。释放锁。synchronized也有两种使用方法:

A、synchronized方法

import java.util.concurrent.*;
import java.util.*; public class ThreadTest implements Runnable {
public synchronized void run() { //声明方式
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
Thread t1 = new Thread(t, "A");
Thread t2 = new Thread(t, "B");
t1.start();
t2.start();
}
}/*
* Output: A0 A1 A2 A3 A4 B0 B1 B2 B3 B4
*/// :~

要注意的是,全部对象都自己主动含有单一的锁(也称为监视器)。所以当ThreadTest对象调用synchronized方法时,此对象被加锁,这意味着。其它线程不能调用此对象的全部synchronized方法。
可是假设把一个复杂的方法声明为synchronized,会减少程序执行的效率,所以synchronized块是非常好的解决方法。

B、synchronized块

import java.util.concurrent.*;
import java.util.*; public class ThreadTest {
public void g() {
synchronized (this) { //声明方式
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
} public static void main(String[] args) {
final ThreadTest t = new ThreadTest();
Thread t1 = new Thread(new Runnable() {
public void run() {
t.g();
}
}, "A");
Thread t2 = new Thread(new Runnable() {
public void run() {
t.g();
}
}, "B");
t1.start();
t2.start();
}
}
/*
* Output: A0 A1 A2 A3 A4 B0 B1 B2 B3 B4
*/// :~

当一个线程在訪问object对象的一个synchronized(this)同步代码块时,其他线程仍然能够訪问此对象的非同步代码块。

当然假设不是同一个对象

,synchronized是无法实现相互排斥的。以下是第一句话的代码:

import java.util.concurrent.*;
import java.util.*; public class ThreadTest {
public void g() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
} public void h() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
public static void main(String[] args) {
final ThreadTest t = new ThreadTest();
Thread t1 = new Thread(new Runnable() {
public void run() {
t.g();
}
}, "A");
Thread t2 = new Thread(new Runnable() {
public void run() {
t.h();
}
}, "B");
t1.start();
t2.start();
}
}
/*
* Output:A0 B0 A1 B1 A2 B2 A3 B3 A4 B4
*/// :~

2、Lock

Lock和synchronized的差别就是:

synchronized:当A和B同一时候要訪问C资源,而A获得了对象C的锁。B将一直等待A释放对C的锁,不能被中断。

Lock:B等待一定时间后,A还不释放C,B就会中断等待。

它的基本使用方法:

Lock l = new ReentrantLock();
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}

从代码也能够看出,l.unlock()在finally{}中。这表示终于会被解锁。

3、volatile

用volatile修饰的变量。线程在每次使用变量的时候,都会读取变量改动后的最的值,它能避免因编译器优化导致的读值不准确,

然而它非常easy被误用。

比方仅仅使用volatile变量来实现的累加器,无法得到正确结果。由于JAVA中的自增操作++,

并非原子性操作,在自增过程中还是出现了多线程间的交互。

JAVA学习笔记 -- 多线程之共享资源的更多相关文章

  1. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  2. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  3. java学习笔记 --- 多线程(线程安全问题——同步代码块)

    1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...

  4. java学习笔记 --- 多线程(多线程的创建方式)

    1.创建多线程方式1——继承Thread类. 步骤:  A:自定义类MyThread继承Thread类.  B:MyThread类里面重写run()? 为什么是run()方法呢? C:创建对象 D:启 ...

  5. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  6. 0040 Java学习笔记-多线程-线程run()方法中的异常

    run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ...

  7. 0039 Java学习笔记-多线程-线程控制、线程组

    join线程 假如A线程要B线程去完成一项任务,在B线程完成返回之前,不进行下一步执行,那么就可以调用B线程的join()方法 join()方法的重载: join():等待不限时间 join(long ...

  8. java学习笔记 --- 多线程(1)

    1:要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在. 2:什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出现进 ...

  9. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

随机推荐

  1. 手机端图片插件可缩放 旋转 全屏查看photoswipe

    官方介绍PhotoSwipe 是专为移动触摸设备设计的相册/画廊.兼容所有iPhone.iPad.黑莓6+,以及桌面浏览器.底层实现基于HTML/CSS/JavaScript,是一款免费开源的相册产品 ...

  2. Getting or Setting Pixels

    Getting or Setting Pixels The safe (slow) way Suppose you are working on an Image<Bgr, Byte>. ...

  3. DRF的过滤与排序

    过滤 对于列表数据可能需要根据字段进行过滤,我们可以通过添加 django-filter 扩展来增强支持. pip install django-filter 在配置文件中增加过滤后端的设置: INS ...

  4. MATLAB求函数零点与极值

    1.      roots函数 针对多项式求零点(详见MATLAB多项式及多项式拟合) 2.      fzero函数 返回一元函数在某个区间内的的零点. x0 = fzero(@(x)x.^2-3* ...

  5. [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 5907  Solved: 2377[Submit][Sta ...

  6. Angular2响应式表单-翻译与概括官网REACTIVE FORMS页面

    本文将半翻译半总结的讲讲ng2官网的另一个未翻译高级教程页面. 原文地址. 文章目的是使用ng2提供的响应式表单技术快速搭出功能完善丰富的界面表单组件. 响应式表单是一项响应式风格的ng2技术,本文将 ...

  7. python 连接ubuntu xampp mysql

    >>> import MySQLdb >>> db=MySQLdb.connect(user="root",passwd="" ...

  8. D - Interesting Calculator 【数值型BFS+优先队列】

    There is an interesting calculator. It has 3 rows of buttons. Row 1: button 0, 1, 2, 3, ..., 9. Pres ...

  9. RabbitMQ (二) 简单队列

    参考:https://blog.csdn.net/vbirdbest/article/details/78583480 简单队列的模型: P : 生产者,即 Producer C : 消费者,即 Co ...

  10. ( 转 ) 什么是 JWT -- JSON WEB TOKEN

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...