Linux同步机制(一) - 线程锁
1 互斥锁
在线程实际运行过程中,我们经常需要多个线程保持同步。
这时可以用互斥锁来完成任务。互斥锁的使用过程中,主要有
pthread_mutex_init
pthread_mutex_destory
pthread_mutex_lock
pthread_mutex_unlock
这几个函数以完成锁的初始化,锁的销毁,上锁和释放锁操作。
1.1 锁的创建
锁可以被动态或静态创建,可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,采用这种方式比较容易理解,互斥锁是pthread_mutex_t的结构体,而这个宏是一个结构常量,如下可以完成静态的初始化锁:
pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;
另外锁可以用pthread_mutex_init函数动态的创建,函数原型如下:
int pthread_mutex_init(pthread_mutex_t*mutex, const pthread_mutexattr_t * attr)
1.2 锁的属性
互斥锁属性可以由pthread_mutexattr_init(pthread_mutexattr_t *mattr)来初始化,然后可以调用其他的属性设置方法来设置其属性。
互斥锁的范围:可以指定是该进程与其他进程的同步还是同一进程内不同的线程之间的同步。可以设置为PTHREAD_PROCESS_SHARE和PTHREAD_PROCESS_PRIVATE。默认是后者,表示进程内使用锁。可以使用
int pthread_mutexattr_setpshared(pthread_mutexattr_t*mattr, int pshared)
pthread_mutexattr_getpshared(pthread_mutexattr_t*mattr,int *pshared)
用来设置与获取锁的范围;
互斥锁的类型:有以下几个取值空间:
PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。
PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。
PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。
可以用
pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type)
pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type)
获取或设置锁的类型。
1.3 锁的释放
调用pthread_mutex_destory之后,可以释放锁占用的资源,但这有一个前提上锁当前是没有被锁的状态。
1.4 锁操作
对锁的操作主要包括加锁 pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁pthread_mutex_trylock()三个。
int pthread_mutex_lock(pthread_mutex_t*mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。
1.5 代码讲解:
代码说明1:互斥锁基本应用
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int count = 0; void* consume(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
printf("************************consume begin lock\n");
printf("************************consumed %d\n",count);
count++;
sleep(2);
printf("************************consume over lock\n");
pthread_mutex_unlock(&mutex);
printf("************************I'm out of pthread_mutex\n");
sleep(1);
} return NULL;
} void* produce( void * arg )
{
while(1)
{
pthread_mutex_lock(&mutex );
printf("product begin lock\n");
printf("produced %d\n", count);
printf("product over lock\n");
pthread_mutex_unlock(&mutex );
printf("I'm out of pthread_mutex\n");
sleep(1);
} return NULL;
} int main( void )
{
pthread_t thread1,thread2;
pthread_create(&thread1, NULL, &produce, NULL );
pthread_create(&thread2, NULL, &consume, NULL );
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
结果说明:
[root@rocket lock-free]# g++ -g -o pthread_mutex_lockpthread_mutex_lock.cpp -lpthread
[root@rocket lock-free]#./pthread_mutex_lock
product begin lock
produced 0
product over lock
I'm out of pthread_mutex
************************consume beginlock
************************consumed 0
/*中间等待了2秒但是product线程没有执行!*/
************************consume overlock
************************I'm out ofpthread_mutex
product begin lock
produced 1
product over lock
I'm out of pthread_mutex
product begin lock
produced 1
product over lock
I'm out of pthread_mutex
************************consume beginlock
************************consumed 1
************************consume overlock
************************I'm out ofpthread_mutex
product begin lock
produced 2
product over lock
I'm out of pthread_mutex
************************consume beginlock
************************consumed 2
************************consume overlock
************************I'm out ofpthread_mutex
代码说明2:pthread_mutext_trylock使用
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int count = 0; void* consume(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
printf("************************consume begin lock\n");
printf("************************consumed %d\n",count);
count++;
sleep(2);
printf("************************consume over lock\n");
pthread_mutex_unlock(&mutex);
printf("************************I'm out of pthread_mutex\n");
sleep(1);
} return NULL;
} void* produce( void * arg )
{
while(1)
{
if(pthread_mutex_trylock(&mutex ) == 0)
{
printf("product begin lock\n");
printf("produced %d\n", count );
printf("product over lock\n");
pthread_mutex_unlock(&mutex);
printf("I'm out of pthread_mutex\n");
sleep(1);
}
else
{
printf("I have try!But i can`t lock the mutex!\n");
sleep(1);
}
} return NULL;
} int main( void )
{
pthread_t thread1,thread2;
pthread_create(&thread1, NULL, &produce, NULL );
pthread_create(&thread2, NULL, &consume, NULL );
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
结果说明:
[root@rocket lock-free]# g++ -g -o pthread_mutex_trylock pthread_mutex_trylock.cpp -lpthread
[root@rocket lock-free]#./pthread_mutex_trylock
************************consume beginlock
************************consumed 0
/* trylock没有成功马上返回! */
I have try!But i can`t lock the mutex!
I have try!But i can`t lock the mutex!
************************consume overlock
************************I'm out ofpthread_mutex
product begin lock
produced 1
product over lock
I'm out of pthread_mutex
************************consume beginlock
************************consumed 1
I have try!But i can`t lock the mutex!
I have try!But i can`t lock the mutex!
************************consume overlock
************************I'm out ofpthread_mutex
product begin lock
produced 2
product over lock
I'm out of pthread_mutex
************************consume beginlock
************************consumed 2
I have try!But i can`t lock the mutex!
I have try!But i can`t lock the mutex!
************************consume overlock
************************I'm out ofpthread_mutex
2 读写锁
读写锁是因为有3种状态,所以可以有更高的并行性。
2.1 特性
一次只有一个线程可以占有写模式的读写锁, 但是可以有多个线程同时占有读模式的读写锁,正是因为这个特性,当读写锁是写加锁状态时,在这个锁被解锁之前, 所有试图对这个锁加锁的线程都会被阻塞。
当读写锁在读加锁状态时, 所有试图以读模式对它进行加锁的线程都可以得到访问权, 但是如果线程希望以写模式对此锁进行加锁, 它必须阻塞直到所有的线程释放锁。
通常,当读写锁处于读模式锁住状态时,如果有另外线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求, 这样可以避免读模式锁长期占用, 而等待的写模式锁请求长期阻塞。
2.2 适用性
读写锁适合于对数据结构的读次数比写次数多得多的情况。因为,读模式锁定时可以共享, 以写模式锁住时意味着独占, 所以读写锁又叫共享-独占锁。
2.3 API初始化和销毁
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功则返回0,出错则返回错误编号
同互斥锁一样,在释放读写锁占用的内存之前,需要先通过pthread_rwlock_destroy对读写锁进行清理工作, 释放由init分配的资源。
2.4 读和写
#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
这3个函数分别实现获取读锁, 获取写锁和释放锁的操作. 获取锁的两个函数是阻塞操作
同样,非阻塞的函数为:
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
非阻塞的获取锁操作, 如果可以获取则返回0,否则返回错误的EBUSY
2.5 代码讲解
代码说明1:读写锁基本应用
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bits/pthreadtypes.h> static pthread_rwlock_t rwlock; //读写锁对象 int count = 0; void *thread_function_read(void *arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
printf("************************%d, read count %d\n", pthread_self(), count);
sleep(1);
pthread_rwlock_unlock(&rwlock);
usleep(100);
} return NULL;
} void *thread_function_write(void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
count++;
printf("************************%d, write count %d\n", pthread_self(), count);
sleep(5);
pthread_rwlock_unlock(&rwlock);
usleep(100);
}
return NULL;
} int main(int argc, char *argv[])
{
pthread_t rpthread1, rpthread2, wpthread; pthread_rwlock_init(&rwlock,NULL); pthread_create(&rpthread1, NULL, thread_function_read, NULL);
pthread_create(&rpthread2, NULL, thread_function_read, NULL);
pthread_create(&wpthread, NULL, thread_function_write, NULL); pthread_join(rpthread1, NULL);
pthread_join(rpthread2, NULL);
pthread_join(wpthread, NULL); pthread_rwlock_destroy(&rwlock);
exit(EXIT_SUCCESS);
}
结果说明:
[root@rocket lock-free]#./pthread_rwlock
/* 2个读线程互相不阻塞 */
************************1442944768,read count 0
************************1432454912,read count 0
/* 写线程阻塞所有其它线程 */
************************1421965056,write count 1
************************1442944768,read count 1
************************1432454912,read count 1
************************1421965056,write count 2
************************1442944768,read count 2
************************1432454912,read count 2
************************1421965056,write count 3
************************1442944768,read count 3
************************1432454912,read count 3
************************1421965056,write count 4
有意思的是,加入去掉上面代码中thread_function_read和thread_function_write中的usleep(100),则会出现以下结果
[root@rocket lock-free]#./pthread_rwlock
************************-1896831232,read count 0
************************-1907321088,read count 0
************************-1907321088,read count 0
************************-1896831232,read count 0
************************-1907321088,read count 0
************************-1896831232,read count 0
************************-1907321088,read count 0
发现抢不到写锁,按我原先的理解,因为reader线程先启动,所以首先是reader抢到锁,reader抢到锁以后,writer阻塞在锁请求上,当reader释放以后,应该轮到writer才对啊,可是不是这样的!当reader释放后再次请求锁时,还是能拿到!writer基本抢不到锁!
查手册写到,"The pthread_rwlock_rdlock() function applies a read lock tothe read-write lock referenced by rwlock. The calling thread acquires the readlock if a writer does not hold the lock and there are no writers blocked on thelock. It is unspecified whether the calling thread acquires the lock when awriter does not hold the lock and there are writers waiting for the lock" 意思就是说,没有writer在等写锁的时辰,reader是可以拿到读锁的。然则没有划定,若是有writer在期待写锁,该若何?
还好,Linux有pthread_rwlockattr_setkind_np这个函数。
enum
{
PTHREAD_RWLOCK_PREFER_READER_NP,
PTHREAD_RWLOCK_PREFER_WRITER_NP,
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
PTHREAD_RWLOCK_DEFAULT_NP =PTHREAD_RWLOCK_PREFER_READER_NP
};
可是直接pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NP);
没用!为啥呢?连man页都没有,所以我思疑这个函数没实现,因而就用debuginfo-install glibc? 装glibc的调试符号,然后用gdb跟进去,发现pthread_rwlockattr_setkind_np确切是有实现的,代码很简单,更改了attr的一个成员变量。那是为啥呢?
再谷歌,终究找到了pthread_rwlockattr_setkind_np的man page,末尾有一段notes,让我年夜汗:
“Setting the value read-write lockkind to PTHREAD_RWLOCK_PREFER_WRITER_NP, results in the same behavior assetting the value to PTHREAD_RWLOCK_PREFER_READER_NP. As long as a readerthread holds the lock the thread holding a write lock will be starved. Settingthe kind value to PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, allows thewriter to run. However, the writer may not be recursive as is implied by thename. “
意思就是说,
PTHREAD_RWLOCK_PREFER_WRITER_NP和PTHREAD_RWLOCK_PREFER_READER_NP是一样滴!应当设置成PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP才对!可是PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP也是名存实亡滴,它才不会recursive 呢。
这样就有了代码说明2:读写锁优先级的使用
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bits/pthreadtypes.h> static pthread_rwlock_t rwlock; //读写锁对象 int count = 0; void *thread_function_read(void *arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
printf("************************%d, read count %d\n", pthread_self(), count);
sleep(1);
pthread_rwlock_unlock(&rwlock);
//usleep(100);
} return NULL;
} void *thread_function_write(void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
count++;
printf("************************%d, write count %d\n", pthread_self(), count);
sleep(1);
pthread_rwlock_unlock(&rwlock);
usleep(100);
}
return NULL;
} int main(int argc, char *argv[])
{
pthread_t rpthread1, rpthread2, wpthread; pthread_rwlockattr_t attr;
pthread_rwlockattr_setkind_np(&attr,PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_rwlock_init(&rwlock, &attr); pthread_create(&rpthread1, NULL, thread_function_read, NULL);
pthread_create(&rpthread2, NULL, thread_function_read, NULL);
pthread_create(&wpthread, NULL, thread_function_write, NULL); pthread_join(rpthread1, NULL);
pthread_join(rpthread2, NULL);
pthread_join(wpthread, NULL); pthread_rwlock_destroy(&rwlock);
exit(EXIT_SUCCESS);
}
运行结果:
[root@rocket lock-free]#./pthread_rwlock_withpriority
************************1529054976,read count 0
************************1518565120,read count 0
************************1508075264,write count 1
************************1529054976,read count 1
************************1518565120,read count 1
************************1508075264,write count 2
************************1529054976,read count 2
************************1518565120,read count 2
************************1508075264,write count 3
这样就不会导致writer饿死。
代码说明3:pthread_rwlock_tryrdlock使用
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bits/pthreadtypes.h> static pthread_rwlock_t rwlock; //读写锁对象 int count = 0; void *thread_function_read(void *arg)
{
int print_count = 0;
while(1)
{
if (pthread_rwlock_tryrdlock(&rwlock) == 0)
{
printf("************************%d, read count %d\n", pthread_self(), count);
sleep(1);
pthread_rwlock_unlock(&rwlock);
usleep(100);
}
else
{
print_count++;
if (print_count % 10 == 0)
{
printf("I have try!But i can`t lock the rdlock!\n");
print_count = 0;
} usleep(100);
}
} return NULL;
} void *thread_function_write(void *arg)
{
while(1)
{
pthread_rwlock_wrlock(&rwlock);
count++;
printf("************************%d, write count %d\n", pthread_self(), count);
sleep(5);
pthread_rwlock_unlock(&rwlock);
usleep(100);
}
return NULL;
} int main(int argc, char *argv[])
{
pthread_t rpthread1, rpthread2, wpthread; pthread_rwlock_init(&rwlock,NULL); pthread_create(&rpthread1, NULL, thread_function_read, NULL);
pthread_create(&rpthread2, NULL, thread_function_read, NULL);
pthread_create(&wpthread, NULL, thread_function_write, NULL); pthread_join(rpthread1, NULL);
pthread_join(rpthread2, NULL);
pthread_join(wpthread, NULL); pthread_rwlock_destroy(&rwlock);
exit(EXIT_SUCCESS);
}
结果说明:
************************1819674368,read count 0
************************1809184512,read count 0
************************1798694656,write count 1
/* trylock没有成功马上返回! */
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
************************1819674368,read count 1
************************1809184512,read count 1
************************1798694656, writecount 2
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
I have try!But i can`t lock therdlock!
3 自旋锁
自旋锁是SMP架构中的一种low-level的同步机制。
当线程A想要获取一把自旋锁而该锁又被其它线程锁持有时,线程A会在一个循环中自旋以检测锁是不是已经可用了。对于自旋锁需要注意:
由于自旋时不释放CPU,因而持有自旋锁的线程应该尽快释放自旋锁,否则等待该自旋锁的线程会一直在那里自旋,这就会浪费CPU时间。
持有自旋锁的线程在sleep之前应该释放自旋锁以便其它线程可以获得自旋锁。(在内核编程中,如果持有自旋锁的代码sleep了就可能导致整个系统挂起)
Pthreads提供的与Spin Lock锁操作相关的API主要有:
intpthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_init(pthread_spinlock_t*, int);
intpthread_spin_lock(pthread_spinlock_t *);
intpthread_spin_trylock(pthread_spinlock_t *);
intpthread_spin_unlock(pthread_spinlock_t *);
3.1 初始化自旋锁
pthread_spin_init用来申请使用自旋锁所需要的资源并且将它初始化为非锁定状态。pshared的取值及其含义:
PTHREAD_PROCESS_SHARED:该自旋锁可以在多个进程中的线程之间共享。
PTHREAD_PROCESS_PRIVATE:仅初始化本自旋锁的线程所在的进程内的线程才能够使用该自旋锁。
3.2 获得一个自旋锁
pthread_spin_lock用来获取(锁定)指定的自旋锁. 如果该自旋锁当前没有被其它线程所持有,则调用该函数的线程获得该自旋锁.否则该函数在获得自旋锁之前不会返回。如果调用该函数的线程在调用该函数时已经持有了该自旋锁,则结果是不确定的。
3.3 尝试获取一个自旋锁
pthread_spin_trylock会尝试获取指定的自旋锁,如果无法获取则理解返回失败。
3.4 释放(解锁)一个自旋锁
pthread_spin_unlock用于释放指定的自旋锁。
3.5 销毁一个自旋锁
pthread_spin_destroy用来销毁指定的自旋锁并释放所有相关联的资源(所谓的所有指的是由pthread_spin_init自动申请的资源)在调用该函数之后如果没有调用pthread_spin_init重新初始化自旋锁,则任何尝试使用该锁的调用的结果都是未定义的。如果调用该函数时自旋锁正在被使用或者自旋锁未被初始化则结果是未定义的。
4 特性对比
|
锁类型 |
锁特性 |
适用场景 |
|
互斥锁mutex |
会导致线程切换 |
一般情况下的首选 |
|
读写锁rwlock |
同一时间只能有一个writer 可以同时有多个reader |
读多写少的场景 |
|
自旋锁spinlock |
不会导致线程切换 会导致CPU利用率升高 适合小代码段 |
小代码段,加锁不是很频繁的场景 |
版权声明:本文为博主原创文章,未经博主允许不得转载。
Linux同步机制(一) - 线程锁的更多相关文章
- 【av68676164(p31-p32)】Windows和Linux同步机制
4.6.1 Windows同步机制 临界区(CRITICAL_SECTION) 在进程内使用,保证仅一个线程可以申请到该对象 临界区内是临界资源的访问 相关的API函数 初始化临界区 WINBASEA ...
- Linux同步机制(二) - 条件变量,信号量,文件锁,栅栏
1 条件变量 条件变量是一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足. 1.1 相关函数 #include <pthread.h> pthread_cond_t cond ...
- linux 同步机制之complete【转】
转自: http://blog.csdn.net/wealoong/article/details/8490654 在Linux内核中,completion是一种简单的同步机制,标志"thi ...
- linux同步机制
很早之前就接触过同步这个概念了,但是一直都很模糊,没有深入地学习了解过,近期有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这两本 ...
- 对JavaScript中异步同步机制以及线程深入了解
今天在网上看到各种对Js异步同步单线程多线程的讨论 经过前辈们的洗礼 加上鄙人小小的理解 就来纸上谈兵一下吧~ Js本身就是单线程的 至于为什么Js是单线程的 那就要追溯到Js的历史了 总而言之 由于 ...
- Linux同步机制 - 多线程开发总结
1 对于CPU开销大的场景,能利用多核,就尽量利用多核(常常自以为某需求的运算量不大,且CPU足够快,就偷懒写个单线程,结果效率很低) 2 使用多线程的时候,默认是加锁的.在加锁保证业务正常的条件下, ...
- Linux同步机制 - 基本概念(死锁,活锁,饿死,优先级反转,护航现象)
死锁(deadlock) 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进 ...
- linux同步机制2
一.并发控制(1)自旋锁得不到资源,会原地打转,直到获得资源为止定义自旋锁 spinlock_t spin;初始化自旋锁 spin_lock_init(lock);获得自旋锁spin_lock(loc ...
- 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第3节 线程同步机制_1_线程安全问题的概述
随机推荐
- [noip2010]关押罪犯 并查集
第一次看的时候想到了并查集,但是不知道怎么实现: 标解,f[i]表示i所属的集合,用f[i+n]表示i所属集合的补集,实现的很巧妙,可以当成一个使用并查集的巧妙应用: #include<iost ...
- Linux 的多线程编程的高效开发经验
http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...
- .NET中JSON的序列化和反序列化
.NET 中有两种方法进行JSON的操作分别需要引用不同的命名空间 1.System.Runtime.Serialization.Json(System.Runtime.Serialization.d ...
- 压测2.0:云压测 + APM = 端到端压测解决方案
从压力测试说起 压力测试是确立系统稳定性的一种测试方法,通常在系统正常运作范围之外进行,以考察其功能极限和隐患.与功能测试不同,压测是以软件响应速度为测试目标的,尤其是针对在较短时间内大量并发用户的访 ...
- JavaScript 堆内存分析新工具 OneHeap
OneHeap 关注于运行中的 JavaScript 内存信息的展示,用可视化的方式还原了 HeapGraph,有助于理解 v8 内存管理. 背景 JavaScript 运行过程中的大部分数据都保存在 ...
- Java中List、Set和Map的区别--转载
List按对象进入的顺序保存对象,不做排序或编辑操作.Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set,而不关心它的顺序--否则应该使用List).Map同样 ...
- 解决Myeclipse 编辑jsp页面卡
解决Myeclipse 编辑jsp页面卡 编辑一个jsp页面时,如果每输入一下,CPU都100%一下,和大家分项一下. 问题: 当你编辑一个jsp页面时,如果每输入一下,CPU都100%一下,3, ...
- POJ 1679 The Unique MST(次小生成树)
题意:求解最小生成树的权值是否唯一,即要我们求次小生成树的权值两种方法求最小生成树,一种用prim算法, 一种用kruskal算法 一:用prim算法 对于给定的图,我们可以证明,次小生成树可以由最小 ...
- lintcode:完美平方
题目 给一个正整数 n, 找到若干个完全平方数(比如1, 4, 9, ... )使得他们的和等于 n.你需要让平方数的个数最少. 样例 给出 n = 12, 返回 3 因为 12 = 4 + 4 + ...
- GSM、3G、LTE、4G
3GPP(The 3rd Generation Partnership Project)3GPP的目标是实现由2G网络到3G网络的平滑过渡,保证未来技术的后向兼容性,支持轻松建网及系统间的漫游和兼容性 ...