const는 C ++ 11에서 스레드 안전을 의미합니까?
C ++ 11 에서 스레드 안전 을 const
의미 한다고 들었습니다 . 그게 사실입니까?
그 의미 하는가 const
에 해당 이제 자바 의 synchronized
?
키워드가 부족 합니까?
C ++ 11 에서 스레드 안전 을
const
의미 한다고 들었습니다 . 그게 사실입니까?
그것은이다 다소 사실 ...
이것이 스레드 안전성에 대한 표준 언어의 말입니다.
[1.10 / 4] 두 식 평가중 하나가 메모리 위치를 수정하고 (1.7) 다른식이동일한 메모리 위치에 액세스하거나 수정하면 충돌이 발생 합니다.
[1.10 / 21] 다른 스레드에서 충돌하는 두 가지 동작이 포함 된 경우프로그램 실행에 데이터 레이스 가 포함됩니다. 그 중 하나는 원자 적이 지 않으며 다른 것보다 먼저 발생하지 않습니다. 이러한 데이터 경쟁은 정의되지 않은 동작을 초래합니다.
이는 데이터 레이스 가 발생 하기에 충분한 조건 일뿐입니다.
- 주어진 일에 대해 두 가지 이상의 동작이 동시에 수행되고 있습니다. 과
- 그들 중 적어도 하나는 글입니다.
표준 라이브러리는 조금 더가는, 그 기반으로 :
[17.6.5.9/1] 이 섹션은 구현이 데이터 경쟁을 방지하기 위해 충족 해야하는 요구 사항을 지정합니다 (1.10). 달리 명시되지 않는 한 모든 표준 라이브러리 기능은 각 요구 사항을 충족해야합니다. 구현시 아래 명시된 사항 이외의 경우 데이터 경쟁을 막을 수 있습니다.
[17.6.5.9/3] C ++ 표준 라이브러리 함수 는를 포함 하여 함수의 비 const 인수를 통해 개체에 직접 또는 간접적으로 액세스하지 않는 한 현재 스레드 이외의 스레드가 액세스 할 수있는 개체 (1.10)를 직접 또는 간접적으로 수정해서는 안됩니다
this
.
간단히 말하면 const
객체에 대한 작업 이 스레드로부터 안전하다고 기대합니다 . 즉, 표준 라이브러리 는 const
자체 유형의 객체에 대한 작업을 수행하는 한 데이터 레이스를 도입하지 않습니다.
- 완전히 읽기로 구성됩니다. 즉, 쓰기가 없습니다. 또는
- 내부적으로 쓰기를 동기화합니다.
이러한 기대가 귀하의 유형 중 하나에 해당되지 않는 경우, 표준 라이브러리의 구성 요소와 함께 직간접 적으로 사용 하면 데이터 경쟁 이 발생할 수 있습니다 . 결론적으로 표준 라이브러리 관점 에서 스레드 안전 을 const
의미 합니다 . 이것은 계약일 뿐이며 컴파일러에 의해 시행되지는 않습니다 . 계약 을 어기면 정의되지 않은 동작이 발생 하며 사용자가 스스로 처리해야합니다. 존재 여부 는 코드 생성에 영향을 미치지 않습니다 (적어도 데이터 레이스 와 관련하여) .const
그 의미 하는가
const
에 해당 이제 자바 의synchronized
?
없음 . 전혀...
사각형을 나타내는 다음과 같이 지나치게 단순화 된 클래스를 고려하십시오.
class rect {
int width = 0, height = 0;
public:
/*...*/
void set_size( int new_width, int new_height ) {
width = new_width;
height = new_height;
}
int area() const {
return width * height;
}
};
멤버 함수는 area
이다 스레드 안전성 ; 그것의 때문이 const
아니라 전적으로 읽기 작업으로 구성되기 때문입니다. 관련된 쓰기가 없으며 데이터 레이스 가 발생하려면 적어도 하나의 쓰기가 필요 합니다. 즉, area
원하는 수만큼 스레드에서 호출 할 수 있으며 항상 올바른 결과를 얻을 수 있습니다.
이 것을 의미하지 않음을 참고 rect
인 스레드 안전 . 사실, 그 쉬운에 대한 호출이있는 경우 방식을 볼 수 area
있었다를 호출하는 것과 같은 시간에 일이 set_size
주어진에가 rect
, 다음 area
(깨진 값도 이상) 오래된 폭과 새로운 높이에 따라 그 결과를 계산 끝낼 수 있었다 .
그러나 확실히하다, rect
아니다 const
는 심지어 않을 것으로 예상 있도록 스레드 안전 결국. 객체는 선언 된 const rect
반면에, 것, 스레드 안전 에는 쓰기가 가능하지 않기 때문에 (그리고 당신이 고려하는 경우 const_cast
원래 선언 뭔가 -ing const
당신이 얻을 정의되지 않은-행동을 하고 그것 뿐이다).
그렇다면 그것은 무엇을 의미합니까?
Let's assume --for the sake of argument-- that multiplication operations are extremely costly and we better avoid them when possible. We could compute the area only if it is requested, and then cache it in case it is requested again in the future:
class rect {
int width = 0, height = 0;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
cached_area_valid = ( width == new_width && height == new_height );
width = new_width;
height = new_height;
}
int area() const {
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
[If this example seems too artificial, you could mentally replace int
by a very large dynamically allocated integer which is inherently non thread-safe and for which multiplications are extremely costly.]
The member-function area
is no longer thread-safe, it is doing writes now and is not internally synchronized. Is it a problem? The call to area
may happen as part of a copy-constructor of another object, such constructor could have been called by some operation on a standard container, and at that point the standard library expects this operation to behave as a read in regard to data races. But we are doing writes!
As soon as we put a rect
in a standard container --directly or indirectly-- we are entering a contract with the Standard Library. To keep doing writes in a const
function while still honoring that contract, we need to internally synchronize those writes:
class rect {
int width = 0, height = 0;
mutable std::mutex cache_mutex;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
if( new_width != width || new_height != height )
{
std::lock_guard< std::mutex > guard( cache_mutex );
cached_area_valid = false;
}
width = new_width;
height = new_height;
}
int area() const {
std::lock_guard< std::mutex > guard( cache_mutex );
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
Note that we made the area
function thread-safe, but the rect
still isn't thread-safe. A call to area
happening at the same time that a call to set_size
may still end up computing the wrong value, since the assignments to width
and height
are not protected by the mutex.
If we really wanted a thread-safe rect
, we would use a synchronization primitive to protect the non-thread-safe rect
.
Are they running out of keywords?
Yes, they are. They have been running out of keywords since day one.
Source: You don't know const
and mutable
- Herb Sutter
참고URL : https://stackoverflow.com/questions/14127379/does-const-mean-thread-safe-in-c11
'Programing' 카테고리의 다른 글
Flex / Lex와 Yacc / Bison의 차이점은 무엇입니까? (0) | 2020.07.22 |
---|---|
“잠금 대기 시간 초과를 초과했습니다. (0) | 2020.07.22 |
Go에서 슬라이스를 어떻게 지우나요? (0) | 2020.07.21 |
html 루비 코드 주위에 link_to를 어떻게 래핑합니까? (0) | 2020.07.21 |
MySQL에서 값을 NULL로 설정 (0) | 2020.07.21 |