包含javaislock的词条
本篇文章给大家谈谈javaislock,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、如何让java程序只运行一次
- 2、自旋锁和互斥锁的区别 java中lock Syntronized区别
- 3、java开发适合软考高级哪个
- 4、Java ArrayList的使用
- 5、Java中Lock,tryLock,lockInterruptibly有什么区别
- 6、java中snchronised和锁的区别
如何让java程序只运行一次
最快的,socket还要用占系统的端口,
其实很简单,java程序启动是,先产生一个.lock的文件,并对此文件加锁,另一个就无法获得锁,听上去很复杂,其实实现很简单。程序如下
private boolean checkLock(){
FileOutputStream fo = null;
File file = new File(".lock");
try {
fo = new FileOutputStream(file);
//加锁,如果程序已经启动就无法获得锁
lock = fo.getChannel().tryLock();
if (lock == null) {
logger.warn("Warning Could not start epayment. this application is still alive.");
return false;
}else{
return true;
}
} catch (FileNotFoundException e) {
logger.error("checkSftp: lock file can't be created.error:" + e);
return false;
}catch (IOException e) {
logger.error("checkSftp: lock file can't be created.error:" + e);
return false;
}
}
自旋锁和互斥锁的区别 java中lock Syntronized区别
自旋锁(Spin lock)
自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是
否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。其作用是为了解决某项资源的互斥使用。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率远
高于互斥锁。虽然它的效率比互斥锁高,但是它也有些不足之处:
1、自旋锁一直占用CPU,他在未获得锁的情况下,一直运行--自旋,所以占用着CPU,如果不能在很短的时 间内获得锁,这无疑会使CPU效率降低。
2、在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数也可能造成死锁,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我们要慎重使用自旋锁,自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。自旋锁适用于锁使用者保持锁时间比较短的情况下。
两种锁的加锁原理
互斥锁:线程会从sleep(加锁)——running(解锁),过程中有上下文的切换,cpu的抢占,信号的发送等开销。
自旋锁:线程一直是running(加锁——解锁),死循环检测锁的标志位,机制不复杂。
互斥锁属于sleep-waiting类型的锁。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和
Core1上。假设线程A想要通过pthread_mutex_lock操作去得到一个临界区的锁,而此时这个锁正被线程B所持有,那么线程A就会被阻塞
(blocking),Core0 会在此时进行上下文切换(Context
Switch)将线程A置于等待队列中,此时Core0就可以运行其他的任务(例如另一个线程C)而不必进行忙等待。而自旋锁则不然,它属于busy-waiting类型的锁,如果线程A是使用pthread_spin_lock操作去请求锁,那么线程A就会一直在
Core0上进行忙等待并不停的进行锁请求,直到得到这个锁为止。
两种锁的区别
互斥锁的起始原始开销要高于自旋锁,但是基本是一劳永逸,临界区持锁时间的大小并不会对互斥锁的开销造成影响,而自旋锁是死循环检测,加锁全程消耗cpu,起始开销虽然低于互斥锁,但是随着持锁时间,加锁的开销是线性增长。
两种锁的应用
互斥锁用于临界区持锁时间比较长的操作,比如下面这些情况都可以考虑
1 临界区有IO操作
2 临界区代码复杂或者循环量大
3 临界区竞争非常激烈
4 单核处理器
至于自旋锁就主要用在临界区持锁时间非常短且CPU资源不紧张的情况下,自旋锁一般用于多核的服务器。
lock与Syntronized的区别
转自自:
java并发之Lock与synchronized的区别
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
两者在锁的相关概念上区别:
1.可重入锁
如果锁具备可重入性,则称作为可重入锁。像synchronized和ReentrantLock都是可重入锁,可重入性在我看来实际上表明了锁的分配机制:基于线程的分配,而不是基于方法调用的分配。举个简单的例子,当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。
看下面这段代码就明白了:
1
2
3
4
5
6
7
8
9
class MyClass
{
public synchronized void method1()
{
method2();
}
public synchronized void method2()
{
}
}
上述代码中的两个方法method1和method2都用synchronized修饰了,假如某一时刻,线程A执行到了method1,此时线程A获取了这个对象的锁,而由于method2也是synchronized方法,假如synchronized不具备可重入性,此时线程A需要重新申请锁。但是这就会造成一个问题,因为线程A已经持有了该对象的锁,而又在申请获取该对象的锁,这样就会线程A一直等待永远不会获取到的锁。
而由于synchronized和Lock都具备可重入性,所以不会发生上述现象。
2.可中断锁
可中断锁:顾名思义,就是可以相应中断的锁。
在Java中,synchronized就不是可中断锁,而Lock是可中断锁。
如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。
在前面演示lockInterruptibly()的用法时已经体现了Lock的可中断性。
3.公平锁
公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。
非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。
在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。
而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。
看一下这2个类的源代码就清楚了:
在ReentrantLock中定义了2个静态内部类,一个是NotFairSync,一个是FairSync,分别用来实现非公平锁和公平锁。
我们可以在创建ReentrantLock对象时,通过以下方式来设置锁的公平性:
1
ReentrantLock
lock = new ReentrantLock(true);
如果参数为true表示为公平锁,为fasle为非公平锁。默认情况下,如果使用无参构造器,则是非公平锁。
另外在ReentrantLock类中定义了很多方法,比如:
isFair() //判断锁是否是公平锁
isLocked() //判断锁是否被任何线程获取了
isHeldByCurrentThread() //判断锁是否被当前线程获取了
hasQueuedThreads() //判断是否有线程在等待该锁
在ReentrantReadWriteLock中也有类似的方法,同样也可以设置为公平锁和非公平锁。不过要记住,ReentrantReadWriteLock并未实现Lock接口,它实现的是ReadWriteLock接口。
4.读写锁
读写锁将对一个资源(比如文件)的访问分成了2个锁,一个读锁和一个写锁。
正因为有了读写锁,才使得多个线程之间的读操作不会发生冲突。
ReadWriteLock就是读写锁,它是一个接口,ReentrantReadWriteLock实现了这个接口。
可以通过readLock()获取读锁,通过writeLock()获取写锁。
性能比较
在JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能最大的影响是阻塞的是实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性带来了很大的压力。相比之下使用Java提供的Lock对象,性能更高一些。Brian
Goetz对这两种锁在JDK1.5、单核处理器及双Xeon处理器环境下做了一组吞吐量对比的实验,发现多线程环境下,synchronized的吞吐量下降的非常严重,而ReentrankLock则能基本保持在同一个比较稳定的水平上。但与其说ReetrantLock性能好,倒不如说synchronized还有非常大的优化余地,于是到了JDK1.6,发生了变化,对synchronize加入了很多优化措施,有自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在JDK1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地,所以还是提倡在synchronized能实现需求的情况下,优先考虑使用synchronized来进行同步。
java开发适合软考高级哪个
java开发适合的软考高级等相关的专业问题,推荐咨询千锋教育。千锋教育拥有国内一体化教学管理及学员服务,在职业教育发展道路上不断探索前行。
java开发适合软考知识点:
1、对多线程的了解,尤其是对线程池的理解,对ThreadPoolExecutor构造参数各个作用的理解、了解Fxied Pool、Cached Pool分别的作用
2、对锁的了解,synchronized、Lock接口(及其对应的实现的理解)
3、对JDK中HaskMap、ArrayList的源代码级别理解;对并发包中ConcurrentHashMap源代码级别的理解(可以基于JDK8、在了解JDK7)
4、熟练使用Mybais、Spring框架
5、对Spring Bean生命周期的理解、Spring 事务管理的理解(主要关注隔离性、事务的几种传播方式)
6、对Spring AOP能够用于哪些场景、实现AOP的核心技术是什么(JDK Proxy、cglib包)
7、对Tomcat的架构有所理解(底层通讯框架是什么:NIO、如何做到隔离:自定义的classloader)
8、对分布式理论的了解(CAP、BASE等)
想要了解更多有关java开发的相关信息,推荐咨询千锋教育。北京千锋互联科技有限公司(下面简称“千锋教育”),成立于2011年1月,立足于职业教育培训领域,公司现有教育培训、高校服务、企业服务三大业务板块。教育培训业务分为大学生技能培训和职后技能培训;高校服务业务主要提供校企合作全解决方案与定制服务;企业服务业务主要为企业提供专业化综合服务
Java ArrayList的使用
import java.util.*;
class Student { // 定义学生类
String name;
Student(String name) { // 构造方法
this.name = name;
}
// 重写equals方法,保证只要名字相等,则认为是同一个人.
public boolean equals(Object obj) {
if (name == null || obj == null) {
return false;
}
if (obj instanceof Student) {
Student sd = (Student) obj;
return name.equals(sd.name);
}
return false;
}
}
public class t2 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
Student[] stu = new Student[4];// 定义
ArrayListStudent stus = new ArrayListStudent();// ArrayList泛型,每个元素是1个学生。
System.out.println("输入4个学生姓名:");
// 初始化4个学生,并将他们添加进ArrayList
for (int i = 0; i 4; i++) {
stu[i] = new Student(reader.nextLine());
stus.add(stu[i]);
}
System.out.println("列表中还有" + stus.size() + "个学生:");
for (int i = 0; i stus.size(); i++) { // 遍历输出所有元素中学生的姓名
System.out.println("第" + i + "个学生: " + stus.get(i).name);
}
// 键盘输入一个学生姓名,判断该学生是否在列表中,如存在,则输出其在列表中的下标,然后将它从列表中移除。
System.out.println("输入要查找的人的姓名:");
Student s = new Student(reader.nextLine());
if (stus.contains(s)) {
System.out.println("找到" + s.name + ",下标为" + stus.indexOf(s));// 输出下标
stus.remove(s); // 从列表中移除该学生
System.out.println("删除" + s.name + "后,还有" + stus.size() + "个学生:");
for (int i = 0; i stus.size(); i++) { // 遍历输出所有元素中学生的姓名
System.out.println("第" + i + "个学生: " + stus.get(i).name);
}
} else
System.out.println("列表中找不到" + s.name); // 如不存在则输出找不到。
}
}
效果
输入4个学生姓名:
天涯
明月
秋水
清泉
列表中还有4个学生:
第0个学生: 天涯
第1个学生: 明月
第2个学生: 秋水
第3个学生: 清泉
输入要查找的人的姓名:
天涯
找到天涯,下标为0
删除天涯后,还有3个学生:
第0个学生: 明月
第1个学生: 秋水
第2个学生: 清泉
Java中Lock,tryLock,lockInterruptibly有什么区别
ReentrantLock锁有好几种,除了常用的lock,tryLock,其中有个lockInterruptibly。先把API粘贴上来lockpublicvoidlock()获取锁。如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。如果当前线程已经保持该锁,则将保持计数加1,并且该方法立即返回。如果该锁被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态,此时锁保持计数被设置为1。指定者:接口Lock中的locklockInterruptiblypublicvoidlockInterruptibly()throwsInterruptedException1)如果当前线程未被中断,则获取锁。2)如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。3)如果当前线程已经保持此锁,则将保持计数加1,并且该方法立即返回。4)如果锁被另一个线程保持,则出于线程调度目的,禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:1)锁由当前线程获得;或者2)其他某个线程中断当前线程。5)如果当前线程获得该锁,则将锁保持计数设置为1。如果当前线程:1)在进入此方法时已经设置了该线程的中断状态;或者2)在等待获取锁的同时被中断。则抛出InterruptedException,并且清除当前线程的已中断状态。6)在此实现中,因为此方法是一个显式中断点,所以要优先考虑响应中断,而不是响应锁的普通获取或重入获取。指定者:接口Lock中的lockInterruptibly抛出:InterruptedException如果当前线程已中断。tryLockpublicbooleantryLock()仅在调用时锁未被另一个线程保持的情况下,才获取该锁。1)如果该锁没有被另一个线程保持,并且立即返回true值,则将锁的保持计数设置为1。即使已将此锁设置为使用公平排序策略,但是调用tryLock()仍将立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用tryLock(0,TimeUnit.SECONDS),它几乎是等效的(也检测中断)。2)如果当前线程已经保持此锁,则将保持计数加1,该方法将返回true。3)如果锁被另一个线程保持,则此方法将立即返回false值。指定者:接口Lock中的tryLock返回:如果锁是自由的并且被当前线程获取,或者当前线程已经保持该锁,则返回true;否则返回false关于中断又是一段很长的叙述,先不谈。1)lock(),拿不到lock就不罢休,不然线程就一直block。比较无赖的做法。2)tryLock(),马上返回,拿到lock就返回true,不然返回false。比较潇洒的做法。带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false。比较聪明的做法。3)lockInterruptibly()就稍微难理解一些。先说说线程的打扰机制,每个线程都有一个打扰标志。这里分两种情况,1.线程在sleep或wait,join,此时如果别的进程调用此进程的interrupt()方法,此线程会被唤醒并被要求处理InterruptedException;(thread在做IO操作时也可能有类似行为,见javathreadapi)2.此线程在运行中,则不会收到提醒。但是此线程的“打扰标志”会被设置,可以通过isInterrupted()查看并作出处理。lockInterruptibly()和上面的第一种情况是一样的,线程在请求lock并被阻塞时,如果被interrupt,则“此线程会被唤醒并被要求处理InterruptedException”。并且如果线程已经被interrupt,再使用lockInterruptibly的时候,此线程也会被要求处理interruptedException先看lock()方法importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***@author作者E-mail:*@version创建时间:2015-10-23下午01:47:03类说明*/publicclassTestLock{//@Testpublicvoidtest()throwsException{finalLocklock=newReentrantLock();lock.lock();Threadt1=newThread(newRunnable(){@Overridepublicvoidrun(){lock.lock();System.out.println(Thread.currentThread().getName()+"interrupted.");}},"childthread-1");t1.start();Thread.sleep(1000);t1.interrupt();Thread.sleep(1000000);}publicstaticvoidmain(String[]args)throwsException{newTestLock().test();}}用eclipse对这个程序进行debug发现,即使子线程已经被打断,但是子线程仍然在run,可见lock()方法并不关心线程是否被打断,甚至说主线程已经运行完毕,子线程仍然在block().而使用LockInterupptibly,则会响应中断importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***@author作者E-mail:*@version创建时间:2015-10-23下午01:53:10类说明*/publicclassTestLockInterruptibly{//@Testpublicvoidtest3()throwsException{finalLocklock=newReentrantLock();lock.lock();Threadt1=newThread(newRunnable(){@Overridepublicvoidrun(){try{lock.lockInterruptibly();}catch(InterruptedExceptione){System.out.println(Thread.currentThread().getName()+"interrupted.");}}},"childthread-1");t1.start();Thread.sleep(1000);t1.interrupt();Thread.sleep(1000000);}publicstaticvoidmain(String[]args)throwsException{newTestLockInterruptibly().test3();}}try{Thread.sleep(2000);lock.lockInterruptibly();}catch(InterruptedExceptione){System.out.println(Thread.currentThread().getName()+"interrupted.");}t1.start();t1.interrupt();Thread.sleep(1000000);如果将代码改成这样,那么将会在在阻塞之前已经中断,此时再lockInterruptibly()也是会相应中断异常的
java中snchronised和锁的区别
在分布式开发中,锁是线程控制的重要途径。Java为此也提供了2种锁机制,synchronized和lock。
我们先从最简单的入手,逐步分析这2种的区别。
一、synchronized和lock的用法区别
synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
用法区别比较简单,这里不赘述了,如果不懂的可以看看Java基本语法。
二、synchronized和lock性能区别
synchronized是托管给JVM执行的,而lock是java写的控制锁的代码。在Java1.5中,synchronize是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。但是到了Java1.6,发生了变化。synchronize在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地。
说到这里,还是想提一下这2中机制的具体区别。据我所知,synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。
现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
我也只是了解到这一步,具体到CPU的算法如果感兴趣的读者还可以在查阅下,如果有更好的解释也可以给我留言,我也学习下。
三、synchronized和lock用途区别
synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。
1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候
javaislock的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、javaislock的信息别忘了在本站进行查找喔。
发布于:2022-11-22,除非注明,否则均为
原创文章,转载请注明出处。