From apple documentation
You only release or autorelease objects you own.
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (to understand when this will be, see “Autorelease Pools”).
Your second two questions are related. All that @synthesize does is to generate additional methods for your implementation file. The arguments to @property (nonatomic, retain) NSString* myString; define the behavior of the generated methods. For example, if you declare a property as retain, the setMyString generated method will retain its argument.
Nonatomic is important because properties, by default, are threadsafe. If you don't need thread safety, you can remove a lot of overhead in your accessor methods.
Finally, the implementation of a retain property is
- (void) setMyString:(NSString*)newString {
[newString retain];
[myString release];
myString = newString;
}
So, saying self.myString = nil effectively releases myString for you. Many people advocate using self.property = nil for retained properties, as opposed to [property release], though I think it just comes down to personal preference.