javamutex
① java 多核处理器下会发生同时获取对象锁的情况吗
对象锁类锁
对象锁
当一个对象中有synchronized method或synchronized block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放
同步静态方法/静态变量互斥体
由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只由一份。所以,一旦一个静态的方法被申明为synchronized。此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类锁。一旦一个静态变量被作为synchronized block的mutex。进入此同步区域时,都要先获得此静态变量的对象锁
类锁
由上述同步静态方法引申出一个概念,那就是类锁。其实系统中并不存在什么类锁。当一个同步静态方法被调用时,系统获取的其实就是代表该类的类对象的对象锁
在程序中获取类锁
可以尝试用以下方式获取类锁
synchronized (xxx.class) {}
synchronized (Class.forName("xxx")) {}
同时获取2类锁
同时获取类锁和对象锁是允许的,并不会产生任何问题,但使用类锁时一定要注意,一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。
② JAVA模拟生产者与消费者实例
使用的生产者和消费者模型具有如下特点:
(1)本实验的多个缓冲区不是环形循环的,也不要求按顺序访问。生产者可以把产品放到目前某一个空缓冲区中。
(2)消费者只消费指定生产者的产品。
(3)在测试用例文件中指定了所有的生产和消费的需求,只有当共享缓冲区的数据满足了所有关于它的消费需求后,此共享缓冲区才可以作为空闲空间允许新的生产者使用。
(4)本实验在为生产者分配缓冲区时各生产者间必须互斥,此后各个生产者的具体生产活动可以并发。而消费者之间只有在对同一产品进行消费时才需要互斥,同时它们在消费过程结束时需要判断该消费对象是否已经消费完毕并清除该产品。
Windows
用来实现同步和互斥的实体。在Windows
中,常见的同步对象有:信号量(Semaphore)、
互斥量(Mutex)、临界段(CriticalSection)和事件(Event)等。本程序中用到了前三个。使用这些对象都分
为三个步骤,一是创建或者初始化:接着请求该同步对象,随即进入临界区,这一步对应于互斥量的
上锁;最后释放该同步对象,这对应于互斥量的解锁。这些同步对象在一个线程中创建,在其他线程
中都可以使用,从而实现同步互斥。当然,在进程间使用这些同步对象实现同步的方法是类似的。
1.用锁操作原语实现互斥
为解决进程互斥进人临界区的问题,可为每类临界区设置一把锁,该锁有打开和关闭两种状态,进程执行临界区程序的操作按下列步骤进行:
①关锁。先检查锁的状态,如为关闭状态,则等待其打开;如已打开了,则将其关闭,继续执行步骤②的操作。
②执行临界区程序。
③开锁。将锁打开,退出临界区。
2.信号量及WAIT,SIGNAL操作原语
信号量的初值可以由系统根据资源情况和使用需要来确定。在初始条件下信号量的指针项可以置为0,表示队列为空。信号量在使用过程中它的值是可变的,但只能由WAIT,SIGNAL操作来改变。设信号量为S,对S的WAIT操作记为WAIT(S),对它的SIGNAL操作记为SIGNAL(S)。
WAIT(S):顺序执行以下两个动作:
①信号量的值减1,即S=S-1;
②如果S≥0,则该进程继续执行;
如果
S(0,则把该进程的状态置为阻塞态,把相应的WAITCB连人该信号量队列的末尾,并放弃处理机,进行等待(直至其它进程在S上执行SIGNAL操作,把它释放出来为止)。
SIGNAL(S):顺序执行以下两个动作
①S值加
1,即
S=S+1;
②如果S)0,则该进程继续运行;
如果S(0则释放信号量队列上的第一个PCB(既信号量指针项所指向的PCB)所对应的进程(把阻塞态改为就绪态),执行SIGNAL操作的进程继续运行。
在具体实现时注意,WAIT,SIGNAL操作都应作为一个整体实施,不允许分割或相互穿插执行。也就是说,WAIT,SIGNAL操作各自都好像对应一条指令,需要不间断地做下去,否则会造成混乱。
从物理概念上讲,信号量S)时,S值表示可用资源的数量。执行一次WAIT操作意味着请求分配一个单位资源,因此S值减1;当S<0时,表示已无可用资源,请求者必须等待别的进程释放了该类资源,它才能运行下去。所以它要排队。而执行一次SIGNAL操作意味着释放一个单位资源,因此S值加1;若S(0时,表示有某些进程正在等待该资源,因而要把队列头上的进程唤醒,释放资源的进程总是可以运行下去的。
---------------
/**
*
生产者
*
*/
public
class
Procer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Procer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
empty.p();
mutex.p();
System.out.println(name+"
inserts
a
new
proct
into
"+buf.nextEmptyIndex);
buf.nextEmptyIndex
=
(buf.nextEmptyIndex+1)%buf.size;
mutex.v();
full.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
---------------
/**
*
消费者
*
*/
public
class
Customer
implements
Runnable{
private
Semaphore
mutex,full,empty;
private
Buffer
buf;
String
name;
public
Customer(String
name,Semaphore
mutex,Semaphore
full,Semaphore
empty,Buffer
buf){
this.mutex
=
mutex;
this.full
=
full;
this.empty
=
empty;
this.buf
=
buf;
this.name
=
name;
}
public
void
run(){
while(true){
full.p();
mutex.p();
System.out.println(name+"
gets
a
proct
from
"+buf.nextFullIndex);
buf.nextFullIndex
=
(buf.nextFullIndex+1)%buf.size;
mutex.v();
empty.v();
try
{
Thread.sleep(1000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
}
-------------------------
/**
*
缓冲区
*
*/
public
class
Buffer{
public
Buffer(int
size,int
nextEmpty,int
nextFull){
this.nextEmptyIndex
=
nextEmpty;
this.nextFullIndex
=
nextFull;
this.size
=
size;
}
public
int
size;
public
int
nextEmptyIndex;
public
int
nextFullIndex;
}
-----------------
/**
*
此类用来模拟信号量
*
*/
public
class
Semaphore{
private
int
semValue;
public
Semaphore(int
semValue){
this.semValue
=
semValue;
}
public
synchronized
void
p(){
semValue--;
if(semValue<0){
try
{
this.wait();
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
}
public
synchronized
void
v(){
semValue++;
if(semValue<=0){
this.notify();
}
}
}
------------------------
public
class
Test
extends
Thread
{
public
static
void
main(String[]
args)
{
Buffer
bf=new
Buffer(10,0,0);
Semaphore
mutex=new
Semaphore(1);
Semaphore
full=new
Semaphore(0);
Semaphore
empty=new
Semaphore(10);
//new
Thread(new
Procer("p001",mutex,full,empty,bf)).start();
Procer
p=new
Procer("p001",mutex,full,empty,bf);
new
Thread(new
Procer("p002",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p003",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p004",mutex,full,empty,bf)).start();
new
Thread(new
Procer("p005",mutex,full,empty,bf)).start();
try{
sleep(3000);
}
catch(Exception
ex)
{
ex.printStackTrace();
}
new
Thread(new
Customer("c001",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c002",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c003",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c004",mutex,full,empty,bf)).start();
new
Thread(new
Customer("c005",mutex,full,empty,bf)).start();
}
}
--------------------------------------------
③ java 如何判断一个线程结束
线程结束时等待也就结束了
------解决方案--------------------------------------------------------
waitforsingleobject当然可以。
或者设一全局变量,线程结束就将其置为某值。在别处读取该值,就可以判断线程是否结束了。
------解决方案--------------------------------------------------------
wait_object_0
表示这个线程已经退出了,wait_timeout是这个线程在此函数返回时候还没退出,但是设置的等待时间已经到了,wait_abandoned是所等待的对象是mutex而非thread,
④ Java如何实现线程之间的互斥
临界区(Critical Section):适合一个进程内的多线程访问公共区域或代码段时使用
Java如何实现线程之间的互斥
互斥量 (Mutex):适合不同进程内多线程访问公共区域或代码段时使用,与临界区相似。
事件(Event):通过线程间触发事件实现同步互斥
信号量(Semaphore):与临界区和互斥量不同,可以实现多个线程同时访问公共区域数据,原理与操作系统中PV操作类似,先设置一个访问公共区域的线程最大连接数,每有一个线程访问共享区资源数就减一,直到资源数小于等于零。
⑤ java线程中的同步锁和互斥锁有什么区别
互斥是通过竞争对资源的独占使用,彼此之间不需要知道对方的存在,执行顺序是一个乱序。
同步是协调多个相互关联线程合作完成任务,彼此之间知道对方存在,执行顺序往往是有序的。
⑥ 写出java多线程程序设计中常用类及方法名,并分别说明它们的作用。
Thread类
System.Threading.Thread类是创建并控制线程,设置其优先级并获取其状态最为常用的类
Mutex类
当两个或更多线程需要同访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex是同步基元,它只向一个线程授予对共享资源的独占访问权。
ReaderWriterLock类
ReaderWriterLock类定义支持单个写线程和多个读线程锁,用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改情况下,ReaderWriterLock类所提供的吞吐量比简单的一次只允许一个线程的锁更高。
ThreadPool类
如果有多个任务需要完成,每个任务需要一个线程,这时应该考虑使用线程池来更有效地管理计算机资源并且从中受益。线程池是执行的多个线程集合,它允许系统添加以线程自动创建和开始的任务到队列中,使用线程池使得系统可以优化线程在CPU使用时的时间碎片。但是要记住在任何特定的时间点,每一个进程一每个线程池只有一个个正在运行的线程。使用ThreadPool类可以使得由线程组成的池可以被系统管理,而使开发人员主要精力集中在工作流的逻辑,而不是线程管理上。
WaitHandle类
WaitHandle类封装等待共享资源的独占访问权的操作系统特定的对象,通常用做同步对象的基类。从该类派生的类定义一个信号传输机制以指示获取或释放对共享资源的独占访问,但使用继承的WaitHandle方法在等待对共享资源的访问时阻塞。使用此类的静态方法阻塞刈割线程,直到一个或多个同步对象接收到信息。
AutoResetEent类
AutoResetEvent类通知正在等待的线程已发生事件,无法继承此类。AutoResetEvent类允许线程通过发信号互相通信,通常此通信涉及线程需要独占访问的资源。
AutoResetEvent类将始终保持终止,直到一个正在等待的线程被释放,此时系统将自动把状态设置为非终止状态。如果没有任何线程丰等待,则状态将保持为终止状态。
⑦ java锁定一个类
不用mutext、synchronized
自己的土方法
假设用户1首先通过竞争得到类A的实例
在class a中的方法getInstance()中 设置A 的静态变量busy=true
当其他用户调用getInstance()的时候如果busy ==true 那么阻塞
while(busy)
{
sleep(1)
}
或者直接返回null 让用户自己判断处理
当用户1使用完毕后,再调用A的方法来让busy=false
public void release(Class a)
{
if(a==null)
{return;}
busy=false;
}
⑧ (java大一题目)多线程
publicclassTest{
publicstaticfinalStringmutex="XXXXXXXXX";
privatestaticintmoney=1000;
publicstaticvoidmain(String[]args){
Threadt1=newThread(newmyThread("A"));
Threadt2=newThread(newmyThread("B"));
t1.start();
t2.start();
}
{
privateStringpeople;
privateintindex=0;
privateinttotal=0;
publicmyThread(Stringpeople){
this.people=people;
}
@Override
publicvoidrun(){
while(true){
synchronized(mutex){
if(money>=0){
inta=(int)(Math.random()*1000+100)/100*100;
if(money<a){
System.out.println("余额不足");
break;
}
money-=a;
total+=a;
index++;
System.out.println(people+"第"+index+"次取"+a+"元,总共取了"+total);
}else{
break;
}
}
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
//TODO自动生成的catch块
e.printStackTrace();
}
}
}
}
}