「java进程上锁」java 进程锁

博主:adminadmin 2022-12-01 00:25:07 68

本篇文章给大家谈谈java进程上锁,以及java 进程锁对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

JAVA中,线程死锁是什么意思

一. 什么是线程

在谈到线程死锁的时候,我们首先必须了解什么是Java线程。一个程序的进程会包含多个线程,一个线程就是运行在一个进程中的一个逻辑流。多线程允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。

线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信较进程简单。笔者的经验是编写多线程序,必须注意每个线程是否干扰了其他线程的工作。每个进程开始生命周期时都是单一线程,称为“主线程”,在某一时刻主线程会创建一个对等线程。如果主线程停滞则系统就会切换到其对等线程。和一个进程相关的线程此时会组成一个对等线程池,一个线程可以杀死其任意对等线程。

因为每个线程都能读写相同的共享数据。这样就带来了新的麻烦:由于数据共享会带来同步问题,进而会导致死锁的产生。

二. 死锁的机制

由多线程带来的性能改善是以可靠性为代价的,主要是因为有可能产生线程死锁。死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不能正常运行。简单的说就是:线程死锁时,第一个线程等待第二个线程释放资源,而同时第二个线程又在等待第一个线程释放资源。这里举一个通俗的例子:如在人行道上两个人迎面相遇,为了给对方让道,两人同时向一侧迈出一步,双方无法通过,又同时向另一侧迈出一步,这样还是无法通过。假设这种情况一直持续下去,这样就会发生死锁现象。

导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。“synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。

Java中每个对象都有一把锁与之对应。但Java不提供单独的lock和unlock操作。下面笔者分析死锁的两个过程“上锁”和“锁死” 。

(1) 上锁

许多线程在执行中必须考虑与其他线程之间共享数据或协调执行状态,就需要同步机制。因此大多数应用程序要求线程互相通信来同步它们的动作,在 Java 程序中最简单实现同步的方法就是上锁。在 Java 编程中,所有的对象都有锁。线程可以使用 synchronized 关键字来获得锁。在任一时刻对于给定的类的实例,方法或同步的代码块只能被一个线程执行。这是因为代码在执行之前要求获得对象的锁。

为了防止同时访问共享资源,线程在使用资源的前后可以给该资源上锁和开锁。给共享变量上锁就使得 Java 线程能够快速方便地通信和同步。某个线程若给一个对象上了锁,就可以知道没有其他线程能够访问该对象。即使在抢占式模型中,其他线程也不能够访问此对象,直到上锁的线程被唤醒、完成工作并开锁。那些试图访问一个上锁对象的线程通常会进入睡眠状态,直到上锁的线程开锁。一旦锁被打开,这些睡眠进程就会被唤醒并移到准备就绪队列中。

(2)锁死

如果程序中有几个竞争资源的并发线程,那么保证均衡是很重要的。系统均衡是指每个线程在执行过程中都能充分访问有限的资源,系统中没有饿死和死锁的线程。当多个并发的线程分别试图同时占有两个锁时,会出现加锁冲突的情形。如果一个线程占有了另一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。

在编写多线程代码时,笔者认为死锁是最难处理的问题之一。因为死锁可能在最意想不到的地方发生,所以查找和修正它既费时又费力。例如,常见的例子如下面这段程序。

public int sumArrays(int[] a1, int[] a2) ...{ int value = 0; int size = a1.length; if (size == a2.length) ...{ synchronized(a1) ...{ //1 synchronized(a2) ...{ //2 for (int i=0; isize; i++) value += a1[i] + a2[i]; } } } return value; }

这段代码在求和操作中访问两个数组对象之前锁定了这两个数组对象。它形式简短,编写也适合所要执行的任务;但不幸的是,它有一个潜在的问题。这个问题就是它埋下了死锁的种子。

没有完结,请楼主看下面的网址。

Java中如果几个进程同时写一个文件,加锁后,其他进程会放弃,还是等着?

如果你确定你写的是进程而不是线程的话,放弃还是等着就取决于代码了。如果操作加锁文件会抛出io异常,如果捕捉到异常catch块里放弃那就放弃了,如果捕捉到异常后在catch块里一直重新尝试再次操作就是等着了

java中多线程使用lock锁 其中一个使用unlock方法为什么锁就失效了

Java中Lock,tryLock,lockInterruptibly的区别如下:

一、 lock()方法

使用lock()获取锁,若获取成功,标记下是该线程获取到了锁(用于锁重入),然后返回。若获取失败,这时跑一个for循环,循环中先将线程阻塞放入等待队列,当被调用signal()时线程被唤醒,这时进行锁竞争(因为默认使用的是非公平锁),如果此时用CAS获取到了锁那么就返回,如果没获取到那么再次放入等待队列,等待唤醒,如此循环。其间就算外部调用了interrupt(),循环也会继续走下去。一直到当前线程获取到了这个锁,此时才处理interrupt标志,若有,则执行 Thread.currentThread().interrupt(),结果如何取决于外层的处理。lock()最终执行的方法如下:

[java] view plain copy

final boolean acquireQueued(final Node node, int arg) {

boolean failed = true;

try {

boolean interrupted = false;

for (;;) {

final Node p = node.predecessor();

if (p == head tryAcquire(arg)) { //如果竞争得到了锁

setHead(node);

p.next = null; // help GC

failed = false;

return interrupted; //获取成功返回interrupted标志

}

// 只修改标志位,不做其他处理

if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())

interrupted = true;

}

} finally {

if (failed)

cancelAcquire(node);

}

}

其中parkAndCheckInterrupt()调用了LockSupport.park(),该方法使用Unsafe类将进程阻塞并放入等待队列,等待唤醒,和await()有点类似。

可以看到循环中检测到了interrupt标记,但是仅做 interrupted = true 操作,直到获取到了锁,才return interrupted,然后处理如下

[java] view plain copy

public final void acquire(int arg) {

if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

selfInterrupt(); // 执行Thread.currentThread().interrupt()

}

二、 lockInterruptibly()方法

和lock()相比,lockInterruptibly()只有略微的修改,for循环过程中,如果检测到interrupt标志为true,则立刻抛出InterruptedException异常,这时程序变通过异常直接返回到最外层了,又外层继续处理,因此使用lockInterruptibly()时必须捕捉异常。lockInterruptibly()最终执行的方法如下:

[java] view plain copy

private void doAcquireInterruptibly(int arg)

throws InterruptedException {

final Node node = addWaiter(Node.EXCLUSIVE);

boolean failed = true;

try {

for (;;) {

final Node p = node.predecessor();

if (p == head tryAcquire(arg)) {

setHead(node);

p.next = null; // help GC

failed = false;

return; //获取成功返回

}

if (shouldParkAfterFailedAcquire(p, node)

parkAndCheckInterrupt())

throw new InterruptedException(); //直接抛出异常

}

} finally {

if (failed)

cancelAcquire(node);

}

}

三、 tryLock()方法

使用tryLock()尝试获取锁,若获取成功,标记下是该线程获取到了锁,然后返回true;若获取失败,此时直接返回false,告诉外层没有获取到锁,之后的操作取决于外层,代码如下:

[java] view plain copy

final boolean nonfairTryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

}

else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc 0) // overflow

throw new Error("Maximum lock count exceeded");

setState(nextc);

return true;

}

return false;

}

java程序锁和数据库锁

java程序锁一般对于线程而言。而数据库锁,则相对于进程来说。

北大青鸟java培训:如何避免死锁?

什么是死锁,如何避免死锁?线程A需要资源X,而线程B需要资源Y,而双方都掌握有对方所要的资源,这种情况称为死锁(deadlock),或死亡拥抱(thedeadlyembrace)。

在并发程序设计中,江西电脑培训建议死锁(deadlock)是一种十分常见的逻辑错误。

通过采用正确的编程方式,死锁的发生不难避免。

死锁的四个必要条件在计算机专业的教材中,通常都会介绍死锁的四个必要条件。

这四个条件缺一不可,或者说只要破坏了其中任何一个条件,死锁就不可能发生。

我们来复习一下,这四个条件是:互斥(Mutualexclusion):存在这样一种资源,它在某个时刻只能被分配给一个执行绪(也称为线程)使用;持有(Holdandwait):当请求的资源已被占用从而导致执行绪阻塞时,资源占用者不但无需释放该资源,而且还可以继续请求更多资源;不可剥夺(Nopreemption):执行绪获得到的互斥资源不可被强行剥夺,换句话说,只有资源占用者自己才能释放资源;环形等待(Circularwait):若干执行绪以不同的次序获取互斥资源,从而形成环形等待的局面,想象在由多个执行绪组成的环形链中,每个执行绪都在等待下一个执行绪释放它持有的资源。

解除死锁的必要条件不难看出,在死锁的四个必要条件中,第二、三和四项条件比较容易消除。

通过引入事务机制,往往可以消除第二、三两项条件,方法是将所有上锁操作均作为事务对待,一旦开始上锁,即确保全部操作均可回退,同时通过锁管理器检测死锁,并剥夺资源(回退事务)。

这种做法有时会造成较大开销,而且也需要对上锁模式进行较多改动。

消除第四项条件是比较容易且代价较低的办法。

具体来说这种方法约定:上锁的顺序必须一致。

具体来说,我们人为地给锁指定一种类似“水位”的方向性属性。

无论已持有任何锁,该执行绪所有的上锁操作,必须按照一致的先后顺序从低到高(或从高到低)进行,且在一个系统中,只允许使用一种先后次序。

请注意,放锁的顺序并不会导致死锁。

也就是说,尽管按照锁A,锁B,放A,放B这样的顺序来进行锁操作看上去有些怪异,但是只要大家都按先A后B的顺序上锁,便不会导致死锁。

解决方法:1使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务(细化处理逻辑,执行一段逻辑后便回滚或者提交,然后再执行其它逻辑,直到事物执行完毕提交);2设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂; 3优化程序,检查并避免死锁现象出现; 4对所有的脚本和SP都要仔细测试,在正是版本之前。

 5所有的SP都要有错误处理(通过@error) 6一般不要修改SQLSERVER事务的默认级别。

不推荐强行加锁另外参考的解决方法:按同一顺序访问对象如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。

例如,如果两个并发事务获得Supplier表上的锁,然后获得Part表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在Supplier表上。

第一个事务提交或回滚后,第二个事务继续进行。

不发生死锁。

将存储过程用于所有的数据修改可以标准化访问对象的顺序。

关于java进程上锁和java 进程锁的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

The End

发布于:2022-12-01,除非注明,否则均为首码项目网原创文章,转载请注明出处。