读写锁实现例子

读写锁实现例子
读写锁实现例子

#include

#include

#include

#include

#include

#include

#include

using namespace std;

using boost::this_thread::sleep;

using boost::posix_time::milliseconds;

const int MAX_READLOCK= 10;// 读操作限制数const int READTHREAD_NUM= 15;// 读线程数

class CRWMutex:public boost::mutex

{

public:

// 读锁辅助类

class RLock

{

private:

CRWMutex*m_pMutex;

RLock(const RLock&);

RLock&operator=(const RLock&);

public:

RLock(CRWMutex&m):m_pMutex(&m)

{

m_pMutex->ReadLock();

}

~RLock()

{

m_pMutex->Unlock();

}

};

// 写锁辅助类

class WLock

{

private:

CRWMutex*m_pMutex;

WLock(const RLock&);

WLock&operator=(const RLock&);

public:

WLock(CRWMutex&m):m_pMutex(&m)

{

m_pMutex->WriteLock();

}

~WLock()

{

m_pMutex->Unlock();

}

};

private:

boost::condition_variable_any m_oCondR;

boost::condition_variable_any m_oCondW;

int m_iCntR;// 读操作总数量

int m_iCntRding;// 正在执行中的读操作数量

int m_iCntW;// 写操作总数量

int m_iMaxReadLock;// 读操作数量限制

CRWMutex(const CRWMutex&);

CRWMutex&operator=(const CRWMutex&);

private:

// 是否能够获取读锁

bool TestReadLock()

{

return!((m_iCntW> 0 // 写操作优先检查||m_iCntRding>=m_iMaxReadLock));// 读操作数量越限检查}

// 是否读取或写入中

bool IsActived()

{

return m_iCntRding+m_iCntW>= 2;

}

// 当前锁状态是否为写锁

bool IsWriteLock()

{

return m_iCntW> 0 &&m_iCntRding== 0;

}

bool TestWriteLockNodify()

{

return 0

}

bool TestReadLockNodify()

{

return 0 ==m_iCntW&&m_iCntRding!=m_iCntR;

}

public:

CRWMutex(int max_rd=MAX_READLOCK)

:m_iMaxReadLock(max_rd),m_iCntR(0),m_iCntRding(0),m_iCntW(0)

{

}

~CRWMutex()

{

}

void ReadLock()

{

boost::mutex::scoped_lock lock(*this);

m_iCntR++;

while(!TestReadLock())

{

// 等待读锁

m_oCondR.wait(lock);

}

m_iCntRding++;

time_t now=time(NULL);

printf("r_lock[thread_0x%x] r=%d ring=%d w=%d\tOK\n",

&boost::this_thread::get_id(),m_iCntR,m_iCntRding,m_iCntW);

}

void WriteLock()

{

boost::mutex::scoped_lock lock(*this);

m_iCntW=m_iCntW> 0 ?m_iCntW+ 1 : 1;

time_t now=time(NULL);

while(IsActived())

{

// 等待写或读完成

printf("-w_lock wait r=%d ring=%d w=%d\n",m_iCntR,m_iCntRding,m_iCntW);

m_oCondW.wait(lock);

}

printf("-w_lock[thread_0x%x] get ok r=%d ring=%d w=%d\tOK\n",0,m_iCntR,m_iCntRding, m_iCntW);

}

void Unlock()

{

boost::mutex::scoped_lock lock(*this);

if(IsWriteLock())

{

m_iCntW--;

time_t now=time(NULL);

printf("-w_unlock[thread_0x%x] r=%d w=%d, so singal to rd_cnt\n",

&boost::this_thread::get_id(),m_iCntR,m_iCntW);

// 激活等待中的写或所有读操作

m_iCntW> 0 ?m_oCondW.notify_one():m_oCondR.notify_all();

}

else

{

m_iCntR--;

m_iCntRding--;

time_t now=time(NULL);

printf("r_unlock[thread_0x%x] r=%d ring=%d w=%d\n",

&boost::this_thread::get_id(),m_iCntR,m_iCntRding,m_iCntW);

// 锁状态通知

if(TestWriteLockNodify())

{

// 激活写操作

printf("r_unlock[thread_0x%x] rd_cnt=%d, so singal to wr_cnt[%d]\n",

&boost::this_thread::get_id(),m_iCntR,m_iCntW);

m_oCondW.notify_one();

}

else if(TestReadLockNodify())

{

//激活等待中的读操作

printf("r_unlock[thread_0x%x] rd_cnt=%d wr_cnt=0, so singal to

rding_cnt[%d]\n",

&boost::this_thread::get_id(),m_iCntR,m_iCntRding);

m_oCondR.notify_one();

}

}

}

// 线程安全队列

class CIntQueue

{

private:

boost::mutex m_oMutex;// 锁

vectorm_vecVals;

CIntQueue(const CIntQueue&);

CIntQueue&operator=(const CIntQueue&);

public:

CIntQueue(){}

~CIntQueue(){}

// 入队列

void PushBack(int iVal)throw()

{

boost::mutex::scoped_lock lock(m_oMutex);

m_vecVals.push_back(iVal);

}

// 出队列

int PopBack()throw()

{

boost::mutex::scoped_lock lock(m_oMutex);

int iRet= 0;

if(!m_vecVals.empty())

{

iRet=m_vecVals.back();

m_vecVals.pop_back();

}

return iRet;

}

};

static CRWMutex g_oMutexRW;

static boost::mutex g_oMutexWEnd;

static boost::condition_variable_any g_oCondWEnd; static CIntQueue g_oIntQueue;

static vectorg_vecInts;

static bool g_bThreadEnd=false;

void WriteThread()

const int TIMES_WAITTOINPUT= 30;// 写线程的退出提示static int val= 1;

while(1)

{

{

CRWMutex::WLock oLock(g_oMutexRW);// 获取写锁

val++;

g_oIntQueue.PushBack(val);

g_vecInts.push_back(val);

g_oCondWEnd.notify_one();// 激活一个读线程

sleep(milliseconds(10));

}

#ifdef_DEBUG

// 退出提示

if(val%TIMES_WAITTOINPUT== 0)

{

char line[255];

//printf( "\nExit(Y/N):\n" );

gets(line);

if('Y'==line[0]||'y'==line[0])

{

break;

}

}

#endif

}

{

boost::mutex::scoped_lock lock(g_oMutexWEnd);

g_bThreadEnd=true;

g_oCondWEnd.notify_all();// 激活并结束所有读线程}

return;

}

void ReadThread()

{

static int val= 1;// 读线程数

// 读线程退出条件

while(!g_bThreadEnd)

{

{

//wait for write_end nodify

boost::mutex::scoped_lock lock(g_oMutexWEnd);

g_oCondWEnd.wait(g_oMutexWEnd);

if(g_bThreadEnd)

{

// 退出

break;

}

printf("ReadThread_WakeUp=%d\n",val++);

}

{

CRWMutex::RLock oLock(g_oMutexRW);// 获取读锁

// 打印线程安全队列值

printf("====[thread_0x%x] Queue Value=%d\n",

&boost::this_thread::get_id(),g_oIntQueue.PopBack());

// 打印数组大小

printf("====[thread_0x%x] Vector Size=%d\n",

&boost::this_thread::get_id(),g_vecInts.size());

sleep(milliseconds(1000));

}

sleep(milliseconds(1000));

}

}

int main(int argc,char*argv[])

{

boost::thread thrdw(&WriteThread);

vector>thrdrs;

for(int i= 0;i

{

thrdrs.push_back(boost::shared_ptr(new boost::thread(&ReadThread)));

}

thrdw.join();

for(int i= 0;i

{

thrdrs[i]->join();

}

getchar();

return 0;

}

// 程序输出结果:

//-w_lock[thread_0x0] get ok r=0 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=0 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=0 ring=0 w=1 OK

//ReadThread_WakeUp=1

//-w_unlock[thread_0x66fa24] r=1 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=1 ring=0 w=1 OK

//ReadThread_WakeUp=2

//-w_unlock[thread_0x66fa24] r=2 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=2 ring=0 w=1 OK

//ReadThread_WakeUp=3

//-w_unlock[thread_0x66fa24] r=3 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=3 ring=0 w=1 OK

//ReadThread_WakeUp=4

//-w_unlock[thread_0x66fa24] r=4 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=4 ring=0 w=1 OK

//ReadThread_WakeUp=5

//-w_unlock[thread_0x66fa24] r=5 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=5 ring=0 w=1 OK

//ReadThread_WakeUp=6

//-w_unlock[thread_0x66fa24] r=6 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=6 ring=0 w=1 OK

//ReadThread_WakeUp=7

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//ReadThread_WakeUp=8

//-w_unlock[thread_0x66fa24] r=8 w=0, so singal to rd_cnt //r_lock[thread_0xf6fb40] r=8 ring=1 w=0 OK

//====[thread_0xf6fd44] Queue Value=10

//r_lock[thread_0xe6fb40] r=8 ring=2 w=0 OK

//====[thread_0xf6fd50] Vector Size=9

//====[thread_0xe6fd44] Queue Value=9

//r_lock[thread_0x86fb40] r=8 ring=3 w=0 OK

//====[thread_0xe6fd50] Vector Size=9

//====[thread_0x86fd44] Queue Value=8

//r_lock[thread_0xc6fb40] r=8 ring=4 w=0 OK

//====[thread_0x86fd50] Vector Size=9

//====[thread_0xc6fd44] Queue Value=7

//r_lock[thread_0xa6fb40] r=8 ring=5 w=0 OK

//====[thread_0xc6fd50] Vector Size=9

//====[thread_0xa6fd44] Queue Value=6

//r_lock[thread_0x106fb40] r=8 ring=6 w=0 OK

//====[thread_0xa6fd50] Vector Size=9

//====[thread_0x106fd44] Queue Value=5

//r_lock[thread_0x146fb40] r=8 ring=7 w=0 OK

//====[thread_0x106fd50] Vector Size=9

//====[thread_0x146fd44] Queue Value=4

//r_lock[thread_0x126fb40] r=8 ring=8 w=0 OK

//====[thread_0x146fd50] Vector Size=9

//====[thread_0x126fd44] Queue Value=3

//-w_lock wait r=8 ring=8 w=1

//====[thread_0x126fd50] Vector Size=9

//r_unlock[thread_0xf6fb1c] r=7 ring=7 w=1

//r_unlock[thread_0xe6fb1c] r=6 ring=6 w=1

//r_unlock[thread_0xc6fb1c] r=5 ring=5 w=1

//r_unlock[thread_0xa6fb1c] r=4 ring=4 w=1

//r_unlock[thread_0x86fb1c] r=3 ring=3 w=1

//r_unlock[thread_0x106fb1c] r=2 ring=2 w=1

//r_unlock[thread_0x126fb1c] r=1 ring=1 w=1

//r_unlock[thread_0x146fb1c] r=0 ring=0 w=1

//r_unlock[thread_0x146fb28] rd_cnt=0, so singal to wr_cnt[1] //-w_lock[thread_0x0] get ok r=0 ring=0 w=1 OK

//ReadThread_WakeUp=9

//-w_unlock[thread_0x66fa24] r=1 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=1 ring=0 w=1 OK

//ReadThread_WakeUp=10

//-w_unlock[thread_0x66fa24] r=2 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=2 ring=0 w=1 OK

//ReadThread_WakeUp=11

//-w_unlock[thread_0x66fa24] r=3 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=3 ring=0 w=1 OK

//ReadThread_WakeUp=12

//-w_unlock[thread_0x66fa24] r=4 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=4 ring=0 w=1 OK

//ReadThread_WakeUp=13

//-w_unlock[thread_0x66fa24] r=5 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=5 ring=0 w=1 OK

//ReadThread_WakeUp=14

//-w_unlock[thread_0x66fa24] r=6 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=6 ring=0 w=1 OK

//ReadThread_WakeUp=15

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt

//-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //-w_lock[thread_0x0] get ok r=7 ring=0 w=1 OK

//-w_unlock[thread_0x66fa24] r=7 w=0, so singal to rd_cnt //r_lock[thread_0xd6fb40] r=7 ring=1 w=0 OK

//====[thread_0xd6fd44] Queue Value=30

//r_lock[thread_0x116fb40] r=7 ring=2 w=0 OK

//====[thread_0xd6fd50] Vector Size=29

//====[thread_0x116fd44] Queue Value=29

//r_lock[thread_0x76fb40] r=7 ring=3 w=0 OK

//====[thread_0x116fd50] Vector Size=29

//====[thread_0x76fd44] Queue Value=28

//r_lock[thread_0x96fb40] r=7 ring=4 w=0 OK

//====[thread_0x76fd50] Vector Size=29

//====[thread_0x96fd44] Queue Value=27

//r_lock[thread_0xb6fb40] r=7 ring=5 w=0 OK

//====[thread_0x96fd50] Vector Size=29

//r_lock[thread_0x156fb40] r=7 ring=6 w=0 OK

//====[thread_0xb6fd44] Queue Value=26

//====[thread_0x156fd44] Queue Value=25

//r_lock[thread_0x136fb40] r=7 ring=7 w=0 OK

//====[thread_0xb6fd50] Vector Size=29

//====[thread_0x156fd50] Vector Size=29

//====[thread_0x136fd44] Queue Value=24

//====[thread_0x136fd50] Vector Size=29

//r_unlock[thread_0xd6fb1c] r=6 ring=6 w=0

//r_unlock[thread_0x116fb1c] r=5 ring=5 w=0

//r_unlock[thread_0xb6fb1c] r=4 ring=4 w=0

//r_unlock[thread_0x156fb1c] r=3 ring=3 w=0 //r_unlock[thread_0x76fb1c] r=2 ring=2 w=0 //r_unlock[thread_0x96fb1c] r=1 ring=1 w=0 //r_unlock[thread_0x136fb1c] r=0 ring=0 w=0

死锁问题解决方法

Sqlcode -244 死锁问题解决 版本说明 事件日期作者说明 创建09年4月16日Alan 创建文档 一、分析产生死锁的原因 这个问题通常是因为锁表产生的。要么是多个用户同时访问数据库导致该问题,要么是因为某个进程死了以后资源未释放导致的。 如果是前一种情况,可以考虑将数据库表的锁级别改为行锁,来减少撞锁的机会;或在应用程序中,用set lock mode wait 3这样的语句,在撞锁后等待若干秒重试。 如果是后一种情况,可以在数据库端用onstat -g ses/onstat -g sql/onstat -k等命令找出锁表的进程,用onmode -z命令结束进程;如果不行,就需要重新启动数据库来释放资源。 二、方法一 onmode -u 将数据库服务器强行进入单用户模式,来释放被锁的表。注意:生产环境不适合。 三、方法二 1、onstat -k |grep HDR+X 说明:HDR+X为排他锁,HDR 头,X 互斥。返回信息里面的owner项是正持有锁的线程的共享内存地址。 2、onstat -u |grep c60a363c 说明:c60a363c为1中查到的owner内容。sessid是会话标识符编号。 3、onstat -g ses 20287 说明:20287为2中查到的sessid内容。Pid为与此会话的前端关联的进程标识符。 4、onstat -g sql 20287

说明:20287为2中查到的sessid内容。通过上面的命令可以查看执行的sql语句。 5、ps -ef |grep 409918 说明:409918为4中查到的pid内容。由此,我们可以得到锁表的进程。可以根据锁表进程的重要程度采取相应的处理方法。对于重要且该进程可以自动重联数据库的进程,可以用onmode -z sessid的方法杀掉锁表session。否则也可以直接杀掉锁表的进程 kill -9 pid。 四、避免锁表频繁发生的方法 4.1将页锁改为行锁 1、执行下面sql语句可以查询当前库中所有为页锁的表名: select tabname from systables where locklevel='P' and tabid > 99 2、执行下面语句将页锁改为行锁 alter table tabname lock mode(row) 4.2统计更新 UPDATE STATISTICS; 4.3修改数据库配置onconfig OPTCOMPIND参数帮助优化程序为应用选择合适的访问方法。 ?如果OPTCOMPIND等于0,优化程序给予现存索引优先权,即使在表扫描比较快时。 ?如果OPTCOMPIND设置为1,给定查询的隔离级设置为Repeatable Read时,优化程序才使用索引。 ?如果OPTCOMPIND等于2,优化程序选择基于开销选择查询方式。,即使表扫描可以临时锁定整个表。 *建议设置:OPTCOMPIND 0 # To hint the optimizer 五、起停informix数据库 停掉informix数据库 onmode -ky 启动informix数据库 oninit 注意千万别加-i参数,这样会初始化表空间,造成数据完全丢失且无法挽回。

第3章死锁习题及答案

第三章死锁习题 一、填空题 1.进程的“同步”和“互斥”反映了进程间①和②的关系。 【答案】①直接制约、②间接制约 【解析】进程的同步是指在异步环境下的并发进程因直接制约而互相发送消息,进行相互合作、相互等待,使得各进程按一定的速度执行的过程;而进程的互斥是由并发进程同时共享公有资源而造成的对并发进程执行速度的间接制约。 2.死锁产生的原因是①和②。 【答案】①系统资源不足、②进程推进路径非法 【解析】死锁产生的根本原因是系统的资源不足而引发了并发进程之间的资源竞争。由于资源总是有限的,我们不可能为所有要求资源的进程无限地提供资源。而另一个原因是操作系统应用的动态分配系统各种资源的策略不当,造成并发进程联合推进的路径进入进程相互封锁的危险区。所以,采用适当的资源分配算法,来达到消除死锁的目的是操作系统主要研究的课题之一。 3.产生死锁的四个必要条件是①、②、③、④。 【答案】①互斥条件、②非抢占条件、③占有且等待资源条件、④循环等待条件 【解析】 互斥条件:进程对它所需的资源进行排它性控制,即在一段时间内,某资源为一进程所独占。 非抢占条件:进程所获得的资源在未使用完毕之前,不能被其它进程强行夺走,即只能由获得资源的进程自己释放。 占有且等待资源条件:进程每次申请它所需的一部分资源,在等待新资源的同时,继续占有已分配到的资源, 循环等待条件:存在一进程循环链,链中每一个进程已获得的资源同时被下一个进程所请求。 4.在操作系统中,信号量是表示①的物理实体,它是一个与②有关的整型变量,其值仅能由③原语来改变。 【答案】①资源,②队列,③P-V 【解析】信号量的概念和P-V原语是荷兰科学家E.W.Dijkstra提出来的。信号量是一个特殊的整型量,它与一个初始状态为空的队列相联系。信号量代表了资源的实体,操作系统利用它的状态对并发进程共享资源进行管理。信号量的值只能由P-V原语来改变。 5.每执行一次P原语,信号量的数值S减1。如果S>=0,该进程①;若S<0,则②该进程,并把它插入该③对应的④队列中。 【答案】①继续执行,②阻塞(等待),③信号量,④阻塞(等待) 【解析】从物理概念上讲,S>0时的数值表示某类资源可用的数量。执行一次P原语,意味着请求分配一个单位的资源,因此描述为S=S-1。当S<0时,表示已无资源,这时请求资源的进程将被阻塞,把它排在信号量S的等待队列中。此时,S的绝对值等于信号量队列上的阻塞的进程数目。 6.每执行一次V原语,信号量的数值S加1。如果①,Q进程继续执行;如果S<=0,则从对应的②队列中移出一个进程R,该进程状态变为③。 【答案】①S>0,②等待,③就绪 【解析】执行一次V原语,意味着释放一个单位的资源。因此,描述为S=S+1。当S<0时,表示信号量请求队列中仍然有因请求该资源而被阻塞的进程。因此,应将信号量对应的阻塞队列中的第一个进程唤醒,使之转至就绪队列。 7.利用信号量实现进程的①,应为临界区设置一个信号量mutex。其初值为②,表示该资源尚未使用,临界区应置于③和④原语之间。

线程死锁

主线程A等待另一个线程B的完成才能继续,在线程B中又要更新主线程A的界面,这里涉及了同步问题以及由此可能产生的死锁问题,同步问题在修改后的文章中讲得比较清楚了,对于线程之间可能产生死锁的浅析如下: 在等待线程B中更新主线程A的界面,如果未能正确处理A,B两线程同步的问题,极有可能导致两线程间的死锁 C#线程同步与死锁 在上一讲介绍了使用lock来实现C#线程同步。实际上,这个lock是C#的一个障眼法,在C#编译器编译lock语句时,将其编译成了调用Monitor类。先看看下面的C#源代码: 1.public static void MyLock() 2.{ 3.lock (typeof(Program)) 4. { 5. } 6.} 7. 上面的代码通过lock语句使MyLock同步,这个方法被编译成IL后,代码如图1所示。

图1 从上图被标注的区域可以看到,一条lock语句被编译成了调用Monitor的Enter和Exit方法。Monitor 在System.Threading命名空间中。lock的功能就相当于直接调用Monitor的Entry方法,所不同的是,lock方法在结束后,会自动解除锁定,当然,在IL中是调用了Monitor的Exit方法,但在C#程序中,看起来是自动解锁的,这类似于C#中的using语句,可以自动释放数据库等的资源。但如果直接在C#源程序中使用Monitor类,就必须调用Exit方法来显式地解除锁定。如下面的代码所示: 1.Monitor.Entry(lockObj); 2.try 3.{ 4.// lockObj的同布区 5.} 6.catch(Exception e) 7.{ 8.// 异常处理代码 9.} 10.finally 11.{ 12. Monitor.Exit(lockObj); // 解除锁定

1产生死锁的根本原因是什么

第六章死锁 1.产生死锁的根本原因是什么?死锁发生的必要条件有哪些? 2.阐述预先静态分配法是如何进行死锁预防的。 3.阐述按序分配资源法是如何进行死锁预防的。 4.为什么说不能通过破坏“互斥条件”来预防死锁。 5.防止死锁的分配策略中,它们各自存在的缺点有哪些? 6.在一个真实的计算机机系统中,可用的资源和进程命令对资源的要求都不会持续很久(几个月),资源会损坏或被替换,新的进程会进入和离开系统,新的资源会被购买和添加到系统中。如果用银行家算法控制死锁,下面哪些变化是安全的(不会导致可能的死锁),并且是在什么情况下发生? a. 增加可用资源(新的资源被添加到系统) b. 减少可用资源(资源被从系统中永久性地移出) c. 增加一个进程的Max(进程需要更多的资源,超过所允许给予的资源) d. 减少一个进程的Max(进程不再需要那么多资源) e. 增加进程的数量 f. 减少进程的数量 7.考虑下面的一个系统在某一时刻的状态: Allocation Max Available A B C D A B C D A B C D P00 0 1 2 0 0 1 2 1 5 2 0 P1 1 0 0 0 1 7 5 0 P2 1 3 5 4 2 3 5 6 P30 6 3 2 0 6 5 2 P40 0 1 4 0 6 5 6 使用银行家算法回答下面问题: a. Need矩阵的内容是怎样的? b. 系统是否处于安全状态? c. 如果从进程P1发来一个请求(0,4,2,0),这个请求能否立刻被满足? 8.现有三个进程P1,P2,P3,共享A,B,C这三类资源,进程对资源的需求量和目前分配情况如下: 进程已占资源数最大需求数 A B C A B C P1 2 6 3 2 6 5 P2 2 0 1 4 5 3 P3 2 1 0 2 8 5 若系统还有剩余资源数分别为A类2个,B类6个,C类2个,请按银行家算法回答下列问题:

解决多线程中11个常见问题

并发危险 解决多线程代码中的11 个常见的问题 Joe Duffy 本文将介绍以下内容:?基本并发概念 ?并发问题和抑制措施 ?实现安全性的模式?横切概念本文使用了以下技术: 多线程、.NET Framework 目录 数据争用 忘记同步 粒度错误 读写撕裂 无锁定重新排序 重新进入 死锁 锁保护 戳记 两步舞曲 优先级反转 实现安全性的模式 不变性 纯度 隔离 并发现象无处不在。服务器端程序长久以来都必须负责处理基本并发编程模型,而随着多核处理器的日益普及,客户端程序也将需要执行一些任务。随着并发操作的不断增加,有关确保安全的问题也浮现出来。也就是说,在面对大量逻辑并发操作和不断变化的物理硬件并行性程度时,程序必须继续保持同样级别的稳定性和可靠性。 与对应的顺序代码相比,正确设计的并发代码还必须遵循一些额外的规则。对内存的读写以及对共享资源的访问必须使用同步机制进行管制,以防发生冲突。另外,通常有必要对线程进行协调以协同完成某项工作。 这些附加要求所产生的直接结果是,可以从根本上确保线程始终保持一致并且保证其顺利向前推进。同步和协调对时间的依赖性很强,这就导致了它们具有不确定性,难于进行预测和测试。 这些属性之所以让人觉得有些困难,只是因为人们的思路还未转变过来。没有可供学习的专门API,也没有可进行复制和粘贴的代码段。实际上的确有一组基础概念需要您学习和适应。很可能随着时间的推移某些语言和库会隐藏一些概念,但如果您现在就开始执行并发操作,则不会遇到这种情况。本

文将介绍需要注意的一些较为常见的挑战,并针对您在软件中如何运用它们给出一些建议。 首先我将讨论在并发程序中经常会出错的一类问题。我把它们称为“安全隐患”,因为它们很容易发现并且后果通常比较严重。这些危险会导致您的程序因崩溃或内存问题而中断。 当从多个线程并发访问数据时会发生数据争用(或竞争条件)。特别是,在一个或多个线程写入一段数据的同时,如果有一个或多个线程也在读取这段数据,则会发生这种情况。之所以会出现这种问题,是因为Windows 程序(如C++ 和Microsoft .NET Framework 之类的程序)基本上都基于共享内存概念,进程中的所有线程均可访问驻留在同一虚拟地址空间中的数据。静态变量和堆分配可用于共享。请考虑下面这个典型的例子: static class Counter { internal static int s_curr = 0; internal static int GetNext() { return s_curr++; } } Counter 的目标可能是想为GetNext 的每个调用分发一个新的唯一数字。但是,如果程序中的两个线程同时调用GetNext,则这两个线程可能被赋予相同的数字。原因是s_curr++ 编译包括三个独立的步骤: 1.将当前值从共享的s_curr 变量读入处理器寄存器。 2.递增该寄存器。 3.将寄存器值重新写入共享s_curr 变量。 按照这种顺序执行的两个线程可能会在本地从s_curr 读取了相同的值(比如42)并将其递增到某个值(比如43),然后发布相同的结果值。这样一来,GetNext 将为这两个线程返回相同的数字,导致算法中断。虽然简单语句s_curr++ 看似不可分割,但实际却并非如此。 忘记同步 这是最简单的一种数据争用情况:同步被完全遗忘。这种争用很少有良性的情况,也就是说虽然它们是正确的,但大部分都是因为这种正确性的根基存在问题。 这种问题通常不是很明显。例如,某个对象可能是某个大型复杂对象图表的一部分,而该图表恰好可使用静态变量访问,或在创建新线程或将工作排入线程池时通过将某个对象作为闭包的一部分进行传递可变为共享图表。 当对象(图表)从私有变为共享时,一定要多加注意。这称为发布,在后面的隔离上下文中会对此加以讨论。反之称为私有化,即对象(图表)再次从共享变为私有。 对这种问题的解决方案是添加正确的同步。在计数器示例中,我可以使用简单的联锁: static class Counter { internal static volatile int s_curr = 0; internal static int GetNext() { return Interlocked.Increment(ref s_curr);

操作系统死锁习题集

死锁习题 一、填空题 2.死锁产生的原因是。 3.产生死锁的四个必要条件是、、、。 二、单项选择题 1.两个进程争夺同一个资源。 (A)一定死锁(B)不一定死锁 (C)不死锁(D)以上说法都不对 4.如果发现系统有的进程队

列就说明系统有可能发生死锁了。 (A)互斥(B)可剥夺 (C)循环等待(D)同步 5.预先静态分配法是通过破坏条件,来达到预防死锁目的的。 (A)互斥使用资源/循环等待资源 (B)非抢占式分配/互斥使用资源 (C) 占有且等待资源/循环等待资源 (D)循环等待资源/互斥使用资源 7.下列关于死锁的说法中,正确的是? 1)有环必死锁; 2)死锁必有环; 3)有环无死锁; 4)死锁也无环 8.资源有序分配法的目的是? 1)死锁预防; 2)死锁避免; 3)死锁检测; 4)死锁解除 8.死锁的预防方法中,不太可能的一种方法使()。

A 摈弃互斥条件 B 摈弃请求和保持条件 C 摈弃不剥夺条件 D 摈弃环路等待条件 10. 资源的按序分配策略可以破坏()条件。 A 互斥使用资源 B 占有且等待资源 C 不可剥夺资源 D 环路等待资源 三、多项选择题 1.造成死锁的原因是_________。 (A)内存容量太小(B)系统进程数量太多,系统资源分配不当 (C)CPU速度太慢(D)进程推进顺序不合适 (E)外存容量太小 2.下列叙述正确的是_________。 (A)对临界资源应采取互斥访问方式来实现共享 (B)进程的并发执行会破坏程序的“封

闭性” (C)进程的并发执行会破坏程序的“可再现性” (D)进程的并发执行就是多个进程同时占有CPU (E)系统死锁就是程序处于死循环3.通常不采用_________方法来解除死锁。 (A)终止一个死锁进程(B)终止所有死锁进程 (C)从死锁进程处抢夺资源(D)从非死锁进程处抢夺资源 (E)终止系统所有进程 5.通常使用的死锁防止策略有_________。 (A)动态分配资源(B)静态分配资源 (C)按序分配资源(D)非剥夺式分配资源 (E)剥夺式分配资源 四、名词解释 1死锁

数据库死锁问题总结

数据库死锁问题总结 1、死锁(Deadlock) 所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造 成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系 统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力 协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象 死锁。一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每 个线程都在等待被其他线程占用并堵塞了的资源。例如,如果线程A锁住了记 录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发 生了死锁现象。计算机系统中,如果系统的资源分配策略不当,更常见的可能是 程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。 锁有多种实现方式,比如意向锁,共享-排他锁,锁表,树形协议,时间戳协 议等等。锁还有多种粒度,比如可以在表上加锁,也可以在记录上加锁。(回滚 一个,让另一个进程顺利进行) 产生死锁的原因主要是: (1)系统资源不足。 (2)进程运行推进的顺序不合适。 (3)资源分配不当等。 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能 性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序 与速度不同,也可能产生死锁。 产生死锁的四个必要条件: (1)互斥条件:一个资源每次只能被一个进程使用。 (2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 破解:静态分配(分配全部资源) (3)不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 破解:可剥夺 (4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 破解:有序分配 这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。 死锁的预防和解除:

sql server的死锁及处理方法

【转】处理sql server的死锁 --第一篇 --检测死锁 --如果发生死锁了,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程? --这时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。 use master go create procedure sp_who_lock as begin declare @spid int,@bl int, @intTransactionCountOnEntry int, @intRowcount int, @intCountProperties int, @intCounter int create table #tmp_lock_who ( id int identity(1,1), spid smallint, bl smallint) IF @@ERROR<>0 RETURN @@ERROR insert into #tmp_lock_who(spid,bl) select 0 ,blocked from (select * from sysprocesses where blocked>0 ) a where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid) union select spid,blocked from sysprocesses where blocked>0 IF @@ERROR<>0 RETURN @@ERROR -- 找到临时表的记录数 select @intCountProperties = Count(*),@intCounter = 1 from #tmp_lock_who IF @@ERROR<>0 RETURN @@ERROR

《操作系统原理》5资源管理(死锁)习题

第五章死锁练习题 (一)单项选择题 1.系统出现死锁的根本原因是( )。 A.作业调度不当B.系统中进程太多C.资源的独占性D.资源管理和进程推进顺序都不得当 2.死锁的防止是根据( )采取措施实现的。 A.配置足够的系统资源B.使进程的推进顺序合理 C.破坏产生死锁的四个必要条件之一D.防止系统进入不安全状态 3.采用按序分配资源的策略可以防止死锁.这是利用了使( )条件不成立。 A.互斥使用资源B循环等待资源C.不可抢夺资源D.占有并等待资源 4.可抢夺的资源分配策略可预防死锁,但它只适用于( )。 A.打印机B.磁带机C.绘图仪D.主存空间和处理器 5.进程调度算法中的( )属于抢夺式的分配处理器的策略。 A.时间片轮转算法B.非抢占式优先数算法C.先来先服务算法D.分级调度算法 6.用银行家算法避免死锁时,检测到( )时才分配资源。 A.进程首次申请资源时对资源的最大需求量超过系统现存的资源量 B.进程己占用的资源数与本次申请资源数之和超过对资源的最大需求量 C.进程已占用的资源数与本次申请的资源数之和不超过对资源的最大需求量,且现存资源能满足尚需的最大资源量 D进程已占用的资源数与本次申请的资源数之和不超过对资源的最大需求量,且现存资源能满足本次申请量,但不能满足尚需的最大资源量 7.实际的操作系统要兼顾资源的使用效率和安全可靠,对资源的分配策略,往往采用( )策略。 A死锁的防止B.死锁的避免C.死锁的检测D.死锁的防止、避免和检测的混合 (二)填空题 1.若系统中存在一种进程,它们中的每一个进程都占有了某种资源而又都在等待其中另一个进程所占用的资源。这种等待永远不能结束,则说明出现了______。 2.如果操作系统对______或没有顾及进程______可能出现的情况,则就可能形成死锁。 3.系统出现死锁的四个必要条件是:互斥使用资源,______,不可抢夺资源和______。 4.如果进程申请一个某类资源时,可以把该类资源中的任意一个空闲资源分配给进程,则说该类资源中的所有资源是______。 5.如果资源分配图中无环路,则系统中______发生。 6.为了防止死锁的发生,只要采用分配策略使四个必要条件中的______。 7.使占有并等待资源的条件不成立而防止死锁常用两种方法:______和______. 8静态分配资源也称______,要求每—个进程在______就申请它需要的全部资源。 9.释放已占资源的分配策略是仅当进程______时才允许它去申请资源。 10.抢夺式分配资源约定,如果一个进程已经占有了某些资源又要申请新资源,而新资源不能满足必须等待时、系统可以______该进程已占有的资源。 11.目前抢夺式的分配策略只适用于______和______。 12.对资源采用______的策略可以使循环等待资源的条件不成立。 13.如果操作系统能保证所有的进程在有限的时间内得到需要的全部资源,则称系统处于______。14.只要能保持系统处于安全状态就可______的发生。 15.______是一种古典的安全状态测试方法。 16.要实现______,只要当进程提出资源申请时,系统动态测试资源分配情况,仅当能确保系统安全时才把资源分配给进程。

4:一个经典的多线程同步问题汇总

一个经典的多线程同步问题 程序描述: 主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 -> sleep(50) -> 全局变量++ -> sleep(0) -> 输出参数和全局变量。 要求: 1.子线程输出的线程序号不能重复。 2.全局变量的输出必须递增。 下面画了个简单的示意图: 分析下这个问题的考察点,主要考察点有二个: 1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。 2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。 下面列出这个程序的基本框架,可以在此代码基础上进行修改和验证。 //经典线程同步互斥问题 #include #include #include long g_nNum; //全局资源 unsigned int__stdcall Fun(void *pPM); //线程函数 const int THREAD_NUM = 10; //子线程个数 int main() { g_nNum = 0;

HANDLE handle[THREAD_NUM]; int i = 0; while (i < THREAD_NUM) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); i++;//等子线程接收到参数时主线程可能改变了这个i的值} //保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); return 0; } unsigned int__stdcall Fun(void *pPM) { //由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来int nThreadNum = *(int *)pPM; //子线程获取参数 Sleep(50);//some work should to do g_nNum++; //处理全局资源 Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); return 0; } 运行结果:

分析linux系统中死锁处理策略

分析linux系统中死锁处理策略 摘要:介绍了死锁的概念、预防、必要条件及linux处理死锁的策略,并对银行家算法进行分析。 关键字:死锁,linux,银行家算法 1.死锁的概念 死锁(Deadlock)是若干进程因系统资源有限且操作不当而造成的带有全局危害性的现象。我们考虑下面这个例子:设系统中只有一台打印机和一台读卡机,它们被进程A和进程B共用。这两台物理设备的特性决定了对它们的使用方式必须是顺序的,即一个进程用完了,另一个进程才能用。进程A和B各自对资源的申请使用情况如下: A:申请读卡机 B:申请打印机 申请打印机申请读卡机 使用读卡机使用打印机 使用打印机使用读卡机 释放读卡机释放打印机 释放打印机释放读卡机 由于进程并行工作,就可能出现这样的执行序列: A:申请读卡机 B:申请打印机 A:申请打印机 B:申请读卡机 所谓死锁就是指在一个进程集合中的每个进程,都在等待仅由该集合中的另一进程才能引发的事件,而无限期地僵持下去的局面。 2.死锁的四个必要条件 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。 非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。 循环等待条件(Circular wait):系统中若干进程组成环路,改环路中每个进程都在等待相邻进程正占用的资源。

3.死锁的预防 1. 破坏互斥的条件 非共享的资源必定具有互斥的条件。例如,一台打印机不能同时被多个进程所共享。 2. 破坏占有且等待的条件 为了使系统中从来不会出现占有且等待的情况,我们要保证无论在什么时候,一个进程都可申请到它没有占有的任何其他资源。 两种策略也有如下缺点: (1)在许多情况下,一个进程在执行之前不可能知道它所需要的全部资源。 (2)资源利用率低。 (3)降低了进程的并发性。 (4)可能出现有的进程总得不到运行的状况(“饥饿”)。 3. 破坏非抢占的条件 产生死锁的第三个必要条件是对已分配资源的非抢占式分配。为破坏这个条件,可采用下述隐式抢占方式:如果一个进程占有某些资源,它还要申请另外的资源,而后者又被别的进程所占有,不能立即分给它,该进程就一定处于等待状态。 4. 破坏循环等待的条件 为了使循环等待的条件从不出现,一种方法是实行资源有序分配策略,即把全部资源事先按类编号,然后依序分配,使得进程在申请、占用资源时不会构成环路,从而不会产生死锁。 4.处理死锁的策略 1.忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,因为传说中鸵鸟看到危险就把头埋在地底下,可能鸵鸟觉得看不到危险也就没危险了吧。跟掩耳盗铃有点像。 2.检测死锁并且恢复。 3.仔细地对资源进行动态分配,以避免死锁。 4.通过破除死锁四个必要条件之一,来防止死锁产生。 检测死锁的代价很大。所有Linux对死锁不作任何处理,这是因为基于成本的考虑选择鸵鸟算法。 5.银行家算法 众所周知,避免死锁的著名算法叫做“银行家算法(Banker’s

操作系统(死锁)试题

第五章死锁 一.选择题 1.为多道程序提供的可共享资源不足时,可能出现死锁。但是,不适当的 C 也可能产生死锁。 (A)进程优先权(B)资源的线性分配 (C)进程推进顺序(D)分配队列优先权 2.采用资源剥夺法可以解除死锁,还可以采用 B 方法解除死锁。 (A)执行并行操作(B)撤销进程 (C)拒绝分配新资源(D)修改信号量 3.产生死锁的四个必要条件是:互斥、 B 循环等待和不剥夺。 (A)请求与阻塞(B)请求与保持 (C)请求与释放(D)释放与阻塞 4.在分时操作系统中,进程调度经常采用算法。 (A)先来先服务(B)最高优先权 (C)时间片轮转(D)随机 5.资源的按序分配策略可以破坏条件。 (A)互斥使用资源(B)占有且等待资源 (C)非抢夺资源(D)循环等待资源 6.在 C 情况下,系统出现死锁。 (A)计算机系统发生了重大故障 (B)有多个封锁的进程同时存在 (C)若干进程因竞争而无休止地相互等待他方释放已占有的资源 (D)资源数远远小于进程数或进程同时申请的资源数量远远超过资源总数 7。银行家算法在解决死锁问题中是用于 B 的。 (A)预防死锁(B)避免死锁 (C)检测死锁(D)解除死锁 8.支持多道程序设计的操作系统在运行过程中,不断地选择新进程运行来实现CPU的共享,但其中不是引起操作系统选择新进程的直接原因。 (A)运行进程的时间片用完 (B)运行进程出错 (C)运行进程要等待某一事件发生 (D)有新进程进入就绪队列 9. 在下列解决死锁的方法中,属于死锁预防策略的是 B 。 (A)银行家算法 (B)有序资源分配法 (C)死锁检测法 (D)资源分配图化简法 二、综合题 1.若系统运行中出现如表所示的资源分配情况,改系统是否安全?如果进程P2此时提出资源申请(1,2,2,2),系统能否将资源分配给它?为什么?

精选大厂java多线程面试题50题

Java多线程50题 1)什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。 2)线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。更多详细信息请点击这里。 3)如何在Java中实现线程? https://www.360docs.net/doc/722518085.html,ng.Thread类的实例就是一个线程但是它需要调用https://www.360docs.net/doc/722518085.html,ng.Runnable接口来执行,由于线程类本身就是调用的 Runnable接口所以你可以继承https://www.360docs.net/doc/722518085.html,ng.Thread类或者直接调用Runnable接口来重写run()方法实现线程。 4)Thread类中的start()和run()方法有什么区别? 这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你

调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。 5)Java中Runnable和Callable有什么不同? Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。 6)Java内存模型是什么? Java内存模型规定和指引Java程序在不同的内存架构、CPU 和操作系统间有确定性地行为。它在多线程的情况下尤其重要。 Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。 ●线程内的代码能够按先后顺序执行,这被称为程序次序 规则。 ●对于同一个锁,一个解锁操作一定要发生在时间上后发 生的另一个锁定操作之前,也叫做管程锁定规则。 ●前一个对Volatile的写操作在后一个volatile的读操作之 前,也叫volatile变量规则。 ●一个线程内的任何操作必需在这个线程的start()调用之 后,也叫作线程启动规则。 ●一个线程的所有操作都会在线程终止之前,线程终止规

数据库解除死锁方法

先查看哪些表被锁住了: 杀进程中的会话: 如果有ora-00031错误,则在后面加immediate;alter system kill session '29,5497' immediate; 如何杀死oracle死锁进程

1.查哪个过程被锁: 查V$DB_OBJECT_CACHE视图: SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER='过程的所属用户' AND CLOCKS!='0'; 2. 查是哪一个SID,通过SID可知道是哪个SESSION: 查V$ACCESS视图: SELECT * FROM V$ACCESS WHERE OWNER='过程的所属用户' AND NAME='刚才查到的过程名'; 3. 查出SID和SERIAL#: 查V$SESSION视图: SELECT SID,SERIAL#,PADDR FROM V$SESSION WHERE SID='刚才查到的SID'; 查V$PROCESS视图: SELECT SPID FROM V$PROCESS WHERE ADDR='刚才查到的PADDR'; 4. 杀进程: (1)先杀ORACLE进程: ALTER SYSTEM KILL SESSION '查出的SID,查出的SERIAL#'; (2)再杀操作系统进程: KILL -9 刚才查出的SPID或ORAKILL 刚才查出的SID 刚才查出的SPID。 Oracle的死锁 查询数据库死锁:

查询出来的结果就是有死锁的session了,下面就是杀掉,拿到上面查询出来的SID和SERIAL#,填入到下面的语句中: alter system kill session 'sid,serial#'; 一般情况可以解决数据库存在的死锁了,或通过session id 查到对应的操作系统进程,在Unix中杀掉操作系统的进程。 然后采用kill (unix)或orakill(windows )。 在Unix中: 经常在Oracle的使用过程中碰到这个问题,所以也总结了一点解决方法。 1)查找死锁的进程: 2)kill掉这个死锁的进程: alter system kill session ‘sid,serial#’; (其中sid=l.session_id) 3)如果还不能解决:

Oracle常见死锁发生的原因以及解决方法

Oracle常见死锁发生的原因以及解决方法 Oracle常见死锁发生的原因以及解决办法 一,删除和更新之间引起的死锁 造成死锁的原因就是多个线程或进程对同一个资源的争抢或相互依赖。这里列举一个对同一个资源的争抢造成死锁的实例。 Oracle 10g, PL/SQL version 9.2 CREATE TABLE testLock( ID NUMBER, test VARCHAR(100) ) COMMIT INSERT INTO testLock VALUES(1,'test1'); INSERT INTO testLock VALUES(2,'test2'); COMMIT; SELECT * FROM testLock 1. ID TEST 2.---------- ---------------------------------- 3. 1 test1 4. 2 test2 死锁现象的重现: 1)在sql 窗口执行:SELECT * FROM testLock FOR UPDATE; -- 加行级锁并对内容进行修改, 不要提交 2)另开一个command窗口,执行:delete from testLock WHERE ID=1; 此时发生死锁(注意此时要另开一个窗口,不然会提示:POST THE CHANGE RECORD TO THE DATABASE. 点yes 后强制commit):

3)死锁查看: 1.SQL> select https://www.360docs.net/doc/722518085.html,ername,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine, s.program from v$session s,v$locked_object l where s.sid = l.session_id; USER NAME SESSION_ID SERIAL# LOCKWAIT STATUS MACHINE PROGRAM 2.---------- ---------- ---------- -------- -------- ---------------------- ------------ 3.SYS 146 104 INACTIVE WORKGROUP\J-THINK PLSQLDev.exe 4.SYS 144 145 20834474 ACTIVE WORKGROUP\J-THINK PLSQLDev. exe 字段说明: Username:死锁语句所用的数据库用户; SID: session identifier,session 标示符,session 是通信双方从开始通信到通信结束期间的一个上下文。 SERIAL#: sid 会重用,但是同一个sid被重用时,serial#会增加,不会重复。 Lockwait:可以通过这个字段查询出当前正在等待的锁的相关信息。 Status:用来判断session状态。Active:正执行SQL语句。Inactive:等待操作。Killed:被标注为删除。 Machine:死锁语句所在的机器。 Program:产生死锁的语句主要来自哪个应用程序。 4)查看引起死锁的语句:

15个Java多线程面试题及答案

15个Java多线程面试题及答案 1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。 2)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提 供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。芯学苑老师强烈建议在你在面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。 3)在java中wait和sleep方法的不同?

通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 4)用Java实现阻塞队列。 这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用Java线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和notify()方法来实现阻塞队列,你可以要求他用最新的Java 5中的并发类来再写一次。 5)用Java写代码来解决生产者——消费者问题。 与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在Java中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。 6)用Java编程一个会导致死锁的程序,你将怎么解决?

死锁原因和解决方法

1 简单的死锁(不同表,相同资源竞争) 连接1 Set nocount on; Use testdb; Go Begin tran Update dbo.T1 set col1 = col1 + 1 where keycol = 2; 目前链接1获取排它锁,并且一直保持。 连接2 Set nocount on; Use testdb; Begin tran Update dbo.T2 set col1 = col1 + 1 where keycol = 2; 链接2获取排它锁,并且一直保持。 连接1 Select col1 from dbo.T2 where keycol = 2; Commit tran 连接1被阻塞,但是这样还不算死锁,可能连接2也许会在某一时刻结束事务,释放连接1需要资源上的锁。 连接2 Select col1 from dbo.T1 where keycol = 2; Commit tran 这样产生死锁,因为每个进程都在等待另外一个进程释放他们所需要的锁。 解决方法: 如果交换事务中访问表的顺序,并假定这种变化不影响应用程序的逻辑,就可以避免这种死锁。如果两个事务按相同的顺序访问表,就不会放生这样的死锁。当你开发以特定顺序访问表的事务时,可以联系这样做,只要有必要这样做而且不影响程序的逻辑就可以。

2 因缺少索引导致的死锁(不同表不同资源无索引竞争) 当筛选列上缺少索引时就会出现这种情况。如果被筛选列上没有索引,SQLSERVER 必须扫描所有的行。因此当一个进程保持了某一行的锁时,其他的进程扫描所有的行已检查他们是否符合筛选器,而不是通过索引直接找到期望的行,这样就会发生冲突。 T1.col1和T1.col2上都没有索引 连接1 Begin tran Update dbo.T1 set col2 = col2 + 1 where col1 = 101; 连接2 Begin tran Update dbo.T2 set col2 = col2 + 1 where col1 = 203; 连接 1 Select col2 from dbo.T2 where col1 = 201; Commit tran 由于col1没有索引,SQL SERVER必须扫描所有行并获取共享锁以检查这些行是否符合筛选器。所以被连接2阻塞。 连接2 Select col2 from dbo.T1 where col1 = 103; Commit tran 同样也给阻塞,并且发生死锁。 解决方法 通过在被筛选列上创建索引,你可以避免死锁。当然,如果两个进程尝试访问相同的资源还是可能发生死锁。

相关文档
最新文档