「java锁案例」java锁的作用
今天给各位分享java锁案例的知识,其中也会对java锁的作用进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、java中死锁的概念是什么给个例子
- 2、如何在Java中使用双重检查锁实现单例
- 3、哪位大哥可以用JAVA举几个简单的小例子帮我演示一下死锁现象?
- 4、一道,java 多线程,变量锁的例子.求解
- 5、JAVA锁机制 有小例子说明最好!
java中死锁的概念是什么给个例子
package lock;
public class Task implements Runnable{
private String lock1 = "lock1"; // 锁1
private String lock2 = "lock2"; // 锁2
private boolean flag = true; // 执行标志
@Override
public void run() {
try {
if(flag){
flag = false;
step1: synchronized (lock1) {//第一个线程查看lock1锁旗标状态,发现可用,为lock1设置锁旗标后,开始执行任务。 此时lock1已经被锁。
System.out.println(Thread.currentThread().getName()+"开始执行第1个任务");
Thread.sleep(100);//睡眠等待,此时线程2在执行
step3: synchronized(lock2){//第一个线程查看lock2锁旗标状态,发现lock2被锁定,等待。
System.out.println(Thread.currentThread().getName()+"开始执行第2个任务");
}
}
}else{
flag = true;
step2: synchronized (lock2) {//第二个线程查看lock2锁旗标状态,发现可用,为lock2设置锁旗标后,开始执行任务。 此时lock2已经被锁。
System.out.println(Thread.currentThread().getName()+"开始执行第1个任务");
Thread.sleep(100);////睡眠等待,此时线程1在执行
step4: synchronized(lock1){//第二个线程查看lock1锁旗标状态,发现lock1被锁定,等待。
System.out.println(Thread.currentThread().getName()+"开始执行第2个任务");
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package lock;
/**
* 死锁测试类
* @author remind
*/
public class Test {
public static void main(String[] args) {
//开启两个线程
Task task = new Task();
new Thread(task,"线程1").start();
new Thread(task,"线程2").start();
}
}
我在里边加入了4个阶段setp1、2、3、4。可以配合看一下。
死锁原理:两个线程,两把锁,同步执行。
1、线程1把锁1的状态设置为占用(锁旗标),然后查看锁2状态,发现锁2状态为被占用,处于等待。
2、线程2把锁2的状态设置为占用(锁旗标),然后查看锁1状态,发现锁1状态为被占用,处于等待。
两个线程互相等待,线程1不释放锁1,等待锁2。线程2不释放锁2,等待锁1。死锁形成。
如何在Java中使用双重检查锁实现单例
单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战。他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例。在整个应用生命周期中,要保证只有一个单例类的实例被创建,双重检查锁(Double checked locking of Singleton)是一种实现方法。顾名思义,在双重检查锁中,代码会检查两次单例类是否有已存在的实例,一次加锁一次不加锁,一次确保不会有多个实例被创建。顺便提一下,在JDK1.5中,Java修复了其内存模型的问题。在JDK1.5之前,这种方法会有问题。本文中,我们将会看到怎样用Java实现双重检查锁的单例类,为什么Java 5之前的版本双重检查锁会有问题,以及怎么解决这个问题。顺便说一下,这也是重要的面试要点,我曾经在金融业和服务业的公司面试被要求手写双重检查锁实现单例模式、相信我,这很棘手,除非你清楚理解了你在做什么。你也可以阅读我的完整列表“单例模式设计问题”来更好的准备面试。
为什么你需要双重检查锁来实现单例类?
一个常见情景,单例类在多线程环境中违反契约。如果你要一个新手写出单例模式,可能会得到下面的代码:
private static Singleton _instance;
public static Singleton getInstance() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}
然后,当你指出这段代码在超过一个线程并行被调用的时候会创建多个实例的问题时,他很可能会把整个getInstance()方法设为同步(synchronized),就像我们展示的第二段示例代码getInstanceTS()方法一样。尽管这样做到了线程安全,并且解决了多实例问题,但并不高效。在任何调用这个方法的时候,你都需要承受同步带来的性能开销,然而同步只在第一次调用的时候才被需要,也就是单例类实例创建的时候。这将促使我们使用双重检查锁模式(double checked locking pattern),一种只在临界区代码加锁的方法。程序员称其为双重检查锁,因为会有两次检查 _instance == null,一次不加锁,另一次在同步块上加锁。这就是使用Java双重检查锁的示例:
public static Singleton getInstanceDC() {
if (_instance == null) { // Single Checked
synchronized (Singleton.class) {
if (_instance == null) { // Double checked
_instance = new Singleton();
}
}
}
return _instance;
}
这个方法表面上看起来很完美,你只需要付出一次同步块的开销,但它依然有问题。除非你声明_instance变量时使用了volatile关键字。没有volatile修饰符,可能出现Java中的另一个线程看到个初始化了一半的_instance的情况,但使用了volatile变量后,就能保证先行发生关系(happens-before relationship)。对于volatile变量_instance,所有的写(write)都将先行发生于读(read),在Java 5之前不是这样,所以在这之前使用双重检查锁有问题。现在,有了先行发生的保障(happens-before guarantee),你可以安全地假设其会工作良好。另外,这不是创建线程安全的单例模式的最好方法,你可以使用枚举实现单例模式,这种方法在实例创建时提供了内置的线程安全。另一种方法是使用静态持有者模式(static holder pattern)。
/*
* A journey to write double checked locking of Singleton class in Java.
*/
class Singleton {
private volatile static Singleton _instance;
private Singleton() {
// preventing Singleton object instantiation from outside
}
/*
* 1st version: creates multiple instance if two thread access
* this method simultaneously
*/
public static Singleton getInstance() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}
/*
* 2nd version : this definitely thread-safe and only
* creates one instance of Singleton on concurrent environment
* but unnecessarily expensive due to cost of synchronization
* at every call.
*/
public static synchronized Singleton getInstanceTS() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}
/*
* 3rd version : An implementation of double checked locking of Singleton.
* Intention is to minimize cost of synchronization and improve performance,
* by only locking critical section of code, the code which creates instance of Singleton class.
* By the way this is still broken, if we don't make _instance volatile, as another thread can
* see a half initialized instance of Singleton.
*/
public static Singleton getInstanceDC() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null) {
_instance = new Singleton();
}
}
}
return _instance;
}
}
这就是本文的所有内容了。这是个用Java创建线程安全单例模式的有争议的方法,使用枚举实现单例类更简单有效。我并不建议你像这样实现单例模式,因为用Java有许多更好的方式。但是,这个问题有历史意义,也教授了并发是如何引入一些微妙错误的。正如之前所说,这是面试中非常重要的一点。在去参加任何Java面试之前,要练习手写双重检查锁实现单例类。这将增强你发现Java程序员们所犯编码错误的洞察力。另外,在现在的测试驱动开发中,单例模式由于难以被模拟其行为而被视为反模式(anti pattern),所以如果你是测试驱动开发的开发者,最好避免使用单例模式。
哪位大哥可以用JAVA举几个简单的小例子帮我演示一下死锁现象?
以下为一具体的Java实例说明死锁:
public class DeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object();
static Object o2 = new Object();
public void run()
{
System.out.println("flag=" + flag);
// 当flag==1锁住o1
if (flag == 1) {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
// 只要锁住o2就完成
synchronized (o2) {
System.out.println("1");
}
}
}
// 如果flag==0锁住o2
if (flag == 0) {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
// 只要锁住o1就完成
synchronized (o1) {
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
// 实例2个线程类
DeadLock td1 = new DeadLock();
DeadLock td2 = new DeadLock();
td1.flag = 1;
td2.flag = 0;
// 开启2个线程
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start();
}
}
一道,java 多线程,变量锁的例子.求解
public class Bank {
public static void main(String[] args){
OneCount A=new OneCount();
double m=10000;
A.setBalance(m);
//A账户上现在有10000元
dealThread dt_jia=new dealThread("甲",-1,A);//创建甲的操作(取)
dealThread dt_ye=new dealThread("乙",1,A);//创建乙的操作(存)
dt_jia.start();
dt_ye.start();
}
}
class OneCount{
private double balance=0;
public synchronized double saveMoney(double money){
//当money为负数时表示取钱
if(money0Math.abs(money)=balance){
return balance=(balance+money);
}else if(money=0){
return balance=(balance+money);
}else{
return -1;
}
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
class dealThread extends Thread{
private double money;
private String user;
private OneCount oc;
public dealThread(String user,double money,OneCount oc){
this.user=user;
this.money=money;
this.oc=oc;
}
public void run(){
while(true){
try{
double blance=oc.saveMoney(money);
System.out.println("用户:"+user+"操作后账户余额"+blance);
Thread.currentThread().sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
JAVA锁机制 有小例子说明最好!
java锁一定要保证锁住的是同一个对象。
一般来说,在方法上上锁,可以用常量字符串,或者静态字符串。看下面的例子。
public class SynTest{
private static String lock = "lockA";
private String a = "abc";
public String setA(String newStr){
/* 因为lock是静态变量,所以只要是SynTest类对象访问该方法时,都会争取这把锁
* 如果lock是成员变量的话,每个SynTest类对象都会有自己的lock变量,那样是锁不
* 上的*/
synchronized(lock){
a = newStr;
}
}
}
当然了,除了上面的方法,还可以使用最新的ReadWriteLock,它的实现与synchronized类似,但都要保证访问的是同一把锁。
关于java锁案例和java锁的作用的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。